Skip to content

Commit

Permalink
Merge pull request #95 from contentful/bugfix/nullfified-links-on-sync
Browse files Browse the repository at this point in the history
Synchronize deleted Links
  • Loading branch information
loudmouth committed Jul 17, 2017
2 parents 72e8fe3 + 006ecae commit 00d6e56
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 71 deletions.
2 changes: 1 addition & 1 deletion .env
@@ -1 +1 @@
CONTENTFUL_SDK_VERSION=0.7.3
CONTENTFUL_SDK_VERSION=0.7.4
2 changes: 1 addition & 1 deletion .envrc
@@ -1 +1 @@
export CONTENFUL_SDK_VERSION=0.7.3
export CONTENFUL_SDK_VERSION=0.7.4
10 changes: 9 additions & 1 deletion CHANGELOG.md
Expand Up @@ -10,14 +10,22 @@ This project adheres to [Semantic Versioning](http://semver.org/) starting from
## Table of contents

#### 0.x Releases
- `0.7.x` Releases - [0.7.0](#070) | [0.7.1](#071) | [0.7.2](#072)) | [0.7.3](#073)
- `0.7.x` Releases - [0.7.0](#070) | [0.7.1](#071) | [0.7.2](#072)) | [0.7.3](#073) | [0.7.4](#074)
- `0.6.x` Releases - [0.6.0](#060) | [0.6.1](#061)
- `0.5.x` Releases - [0.5.0](#050)
- `0.4.x` Releases - [0.4.0](#040) | [0.4.1](#041)
- `0.3.x` Releases - [0.3.0](#030) | [0.3.1](#031)

---

## [`0.7.4`](https://github.com/contentful/contentful.swift/releases/tag/0.7.4)
Released on 2017-07-17

#### Fixed
- Deleted Links in Contentful that were not propagating to CoreData as nullfied managed relationships.

---

## [`0.7.3`](https://github.com/contentful/contentful.swift/releases/tag/0.7.3)
Released on 2017-07-17

Expand Down
2 changes: 1 addition & 1 deletion Config.xcconfig
@@ -1 +1 @@
CONTENTFUL_SDK_VERSION=0.7.3
CONTENTFUL_SDK_VERSION=0.7.4
4 changes: 2 additions & 2 deletions README.md
Expand Up @@ -80,7 +80,7 @@ pod 'Contentful'
You can specify a specific version of Contentful depending on your needs. To learn more about operators for dependency versioning within a Podfile, see the [CocoaPods doc on the Podfile][7].

```ruby
pod 'Contentful', '~> 0.7.3'
pod 'Contentful', '~> 0.7.4'
```

Note that for Swift 2.3 support (contentful.swift `v0.2.3`) you will need to add a post-install script to your Podfile if installing with Cocoapods:
Expand All @@ -100,7 +100,7 @@ end
You can also use [Carthage][8] for integration by adding the following to your `Cartfile`:

```
github "contentful/contentful.swift" ~> 0.7.3
github "contentful/contentful.swift" ~> 0.7.4
```

## License
Expand Down
83 changes: 19 additions & 64 deletions Sources/Client.swift
Expand Up @@ -619,7 +619,11 @@ extension Client {

var parameters = matching
parameters["initial"] = true
return sync(matching: parameters, completion: completion)

let syncCompletion: (Result<SyncSpace>) -> Void = { result in
self.finishSync(for: SyncSpace(syncToken: ""), newestSyncResults: result, completion: completion)
}
return sync(matching: parameters, completion: syncCompletion)
}

/**
Expand Down Expand Up @@ -686,83 +690,34 @@ extension Client {
parameters.removeValue(forKey: "initial")
parameters["sync_token"] = syncSpace.syncToken

// Callback to merge the most recent sync page with the current sync space.
let mergeSyncSpacesCompletion: (Result<SyncSpace>) -> Void = { result in

switch result {
case .success(let newSyncSpace):

// Send messages to persistence layer about the diffs (pre-merge state).
// Must send messages for the first sync space that was originally passed in.
self.sendDiffMessagesToPersistenceIntegration(for: newSyncSpace, resolvingLinksWith: syncSpace)
syncSpace.updateWithDiffs(from: newSyncSpace)

completion(Result.success(syncSpace))
case .error(let error):
completion(Result.error(error))
}
let syncCompletion: (Result<SyncSpace>) -> Void = { result in
self.finishSync(for: syncSpace, newestSyncResults: result, completion: completion)
}

let task = self.sync(matching: parameters, completion: mergeSyncSpacesCompletion)
let task = self.sync(matching: parameters, completion: syncCompletion)
return task
}

fileprivate func sendDiffMessagesToPersistenceIntegration(for syncSpacePage: SyncSpace, resolvingLinksWith originalSyncSpac: SyncSpace?) {

persistenceIntegration?.update(syncToken: syncSpacePage.syncToken)

let allEntries = syncSpacePage.entries + (originalSyncSpac?.entries ?? [])
let allAssets = syncSpacePage.assets + (originalSyncSpac?.assets ?? [])

// Resolve links and send to delegate.
for entry in syncSpacePage.entries {
entry.resolveLinks(against: allEntries, and: allAssets)
persistenceIntegration?.create(entry: entry)
}
// Also resolve links among entries that were returned earlier.
for entry in (originalSyncSpac?.entries ?? []) {
entry.resolveLinks(against: allEntries, and: allAssets)
}

for asset in syncSpacePage.assets {
persistenceIntegration?.create(asset: asset)
}

for deletedAssetId in syncSpacePage.deletedAssets {
persistenceIntegration?.delete(assetWithId: deletedAssetId)
}

for deletedEntryId in syncSpacePage.deletedEntries {
persistenceIntegration?.delete(entryWithId: deletedEntryId)
}

persistenceIntegration?.resolveRelationships()
persistenceIntegration?.save()
}

fileprivate func sync(matching: [String: Any] = [:], completion: @escaping ResultsHandler<SyncSpace>) -> URLSessionDataTask? {

return fetch(url: URL(forComponent: "sync", parameters: matching)) { (result: Result<SyncSpace>) in

if let syncSpace = result.value {

// Whenever we get a page, send the diffs to the persistence integration.
self.sendDiffMessagesToPersistenceIntegration(for: syncSpace, resolvingLinksWith: nil)

if syncSpace.hasMorePages == true { // multipage sync.
self.nextSync(for: syncSpace, matching: matching, completion: completion)
} else {
// Merge all the sync spaces together.
completion(Result.success(syncSpace))
}
if let syncSpace = result.value, syncSpace.hasMorePages == true {
self.nextSync(for: syncSpace, matching: matching, completion: completion)
} else {
completion(result)
}
}
}

fileprivate func sync(matching: [String: Any] = [:]) -> Observable<Result<SyncSpace>> {
let asyncDataTask: AsyncDataTask<[String: Any], SyncSpace> = sync(matching:completion:)
return toObservable(parameter: matching, asyncDataTask: asyncDataTask).observable
fileprivate func finishSync(for syncSpace: SyncSpace, newestSyncResults: Result<SyncSpace>, completion: ResultsHandler<SyncSpace>) {

switch newestSyncResults {
case .success(let newSyncSpace):
syncSpace.updateWithDiffs(from: newSyncSpace, persistenceIntegration: self.persistenceIntegration)
completion(Result.success(syncSpace))
case .error(let error):
completion(Result.error(error))
}
}
}
17 changes: 16 additions & 1 deletion Sources/SyncSpace.swift
Expand Up @@ -101,28 +101,43 @@ public final class SyncSpace: ImmutableMappable {
}
}

internal func updateWithDiffs(from syncSpace: SyncSpace) {
internal func updateWithDiffs(from syncSpace: SyncSpace, persistenceIntegration: PersistenceIntegration?) {

for asset in syncSpace.assets {
assetsMap[asset.sys.id] = asset
persistenceIntegration?.create(asset: asset)
}

// Update and deduplicate all entries.
for entry in syncSpace.entries {
entriesMap[entry.sys.id] = entry
}

// resolve all entries.
for entry in entries {
entry.resolveLinks(against: entries, and: assets)
persistenceIntegration?.create(entry: entry)
}

for deletedAssetId in syncSpace.deletedAssets {
assetsMap.removeValue(forKey: deletedAssetId)
persistenceIntegration?.delete(assetWithId: deletedAssetId)
}

for deletedEntryId in syncSpace.deletedEntries {
entriesMap.removeValue(forKey: deletedEntryId)
persistenceIntegration?.delete(entryWithId: deletedEntryId)
}

// Reset so that we can't send same deletion messages twice.
self.deletedEntries = [String]()
self.deletedAssets = [String]()

syncToken = syncSpace.syncToken

persistenceIntegration?.update(syncToken: syncToken)
persistenceIntegration?.resolveRelationships()
persistenceIntegration?.save()
}

internal func cache(resources: [Resource]) {
Expand Down

0 comments on commit 00d6e56

Please sign in to comment.