diff --git a/LeStorage/ModelObject.swift b/LeStorage/ModelObject.swift index 0497c01..74a9b83 100644 --- a/LeStorage/ModelObject.swift +++ b/LeStorage/ModelObject.swift @@ -15,5 +15,9 @@ open class ModelObject { open func deleteDependencies() throws { } + + open func copyFromServerInstance(_ instance: any Storable) -> Bool { + return false + } } diff --git a/LeStorage/Storable.swift b/LeStorage/Storable.swift index 0ebb76c..319712e 100644 --- a/LeStorage/Storable.swift +++ b/LeStorage/Storable.swift @@ -16,12 +16,15 @@ public protocol Storable: Codable, Identifiable where ID : StringProtocol { /// Returns HTTP methods that do not need to pass the token to the request static func tokenExemptedMethods() -> [HTTPMethod] - + /// A method that deletes the local dependencies of the resource /// Mimics the behavior the cascading delete on the django server /// Typically when we delete a resource, we automatically delete items that depends on it, /// so when we do that on the server, we also need to do it locally func deleteDependencies() throws + + func copyFromServerInstance(_ instance: any Storable) -> Bool + } extension Storable { diff --git a/LeStorage/StoredCollection.swift b/LeStorage/StoredCollection.swift index 60b4068..ac38547 100644 --- a/LeStorage/StoredCollection.swift +++ b/LeStorage/StoredCollection.swift @@ -195,7 +195,7 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti do { let items: [T] = try await self._store.getItems() try self._addOrUpdate(contentOfs: items, shouldSync: false) - self._hasChanged = true +// self._hasChanged = true self.hasLoadedFromServer = true NotificationCenter.default.post(name: NSNotification.Name.CollectionDidLoad, object: self) } catch { @@ -360,7 +360,7 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti /// Writes all the items as a json array inside a file fileprivate func _write() { - Logger.log("Start write...") + Logger.log("Start write to \(T.fileName())...") do { let jsonString: String = try self.items.jsonString() try self._writeToStorageDirectory(content: jsonString, fileName: T.fileName()) @@ -428,7 +428,6 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti /// Creates an API call for the Storable [instance] and an HTTP [method] fileprivate func _createCall(_ instance: T, method: HTTPMethod) throws -> ApiCall { -// let baseURL = try _store.service().baseURL let jsonString = try instance.jsonString() return ApiCall(method: method, dataId: String(instance.id), body: jsonString) } @@ -446,20 +445,14 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti return } - if let apiCall = try self._callForInstance(instance, method: HTTPMethod.post) { - try self._prepareCall(apiCall: apiCall) - - Task { - do { - _ = try await self._store.execute(apiCall: apiCall) - } catch { - self.rescheduleApiCallsIfNecessary() - Logger.error(error) - } + Task { + do { + try await self._synchronize(instance, method: HTTPMethod.post) + } catch { + self.rescheduleApiCallsIfNecessary() + Logger.error(error) } - } - } /// Sends an update api call for the provided [instance] @@ -467,19 +460,15 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti guard self.synchronized, self._sendsUpdate, Store.main.collectionsCanSynchronize else { return } - - if let apiCall = try self._callForInstance(instance, method: HTTPMethod.put) { - try self._prepareCall(apiCall: apiCall) - Task { - do { - _ = try await self._store.execute(apiCall: apiCall) - } catch { - Logger.error(error) - self.rescheduleApiCallsIfNecessary() - } + Task { + do { + try await self._synchronize(instance, method: HTTPMethod.put) + } catch { + self.rescheduleApiCallsIfNecessary() + Logger.error(error) } } - + } /// Sends an delete api call for the provided [instance] @@ -487,21 +476,37 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti guard self.synchronized, Store.main.collectionsCanSynchronize else { return } - - if let apiCall = try self._callForInstance(instance, method: HTTPMethod.delete) { + Task { + do { + try await self._synchronize(instance, method: HTTPMethod.delete) + } catch { + self.rescheduleApiCallsIfNecessary() + Logger.error(error) + } + } + + } + + fileprivate func _synchronize(_ instance: T, method: HTTPMethod) async throws { + if let apiCall = try self._callForInstance(instance, method: method) { try self._prepareCall(apiCall: apiCall) - Task { - do { - _ = try await self._store.execute(apiCall: apiCall) - } catch { - Logger.error(error) - self.rescheduleApiCallsIfNecessary() + try await self._executeApiCall(apiCall) + } + } + + fileprivate func _executeApiCall(_ apiCall: ApiCall) async throws { + let result = try await self._store.execute(apiCall: apiCall) + switch apiCall.method { + case .post: +// DispatchQueue.main.async { + if let instance = self.findById(result.stringId) { + self._hasChanged = instance.copyFromServerInstance(result) } - } - +// } + default: + break } - - + Logger.log("") } // MARK: - Reschedule calls @@ -540,8 +545,10 @@ public class StoredCollection: RandomAccessCollection, SomeCollecti for apiCall in apiCallsCopy { apiCall.attemptsCount += 1 apiCall.lastAttemptDate = Date() + do { - let _ = try await Store.main.execute(apiCall: apiCall) + try await self._executeApiCall(apiCall) +// let _ = try await Store.main.execute(apiCall: apiCall) } catch { Logger.error(error) }