From fb6999a66ce0d02af3ed10debbdf30ab9887c266 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 6 May 2025 17:33:47 +0200 Subject: [PATCH] Sync improvements --- LeStorage/Store.swift | 3 +++ LeStorage/StoreCenter.swift | 41 ++++++++++++++++---------------- LeStorage/SyncedCollection.swift | 2 +- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/LeStorage/Store.swift b/LeStorage/Store.swift index d18fc6c..aa895aa 100644 --- a/LeStorage/Store.swift +++ b/LeStorage/Store.swift @@ -16,6 +16,7 @@ public enum StoreError: Error, LocalizedError { case missingKeychainStore case collectionNotRegistered(type: String) case apiCallCollectionNotRegistered(type: String) + case synchronizationInactive public var errorDescription: String? { switch self { @@ -33,6 +34,8 @@ public enum StoreError: Error, LocalizedError { return "The collection \(type) is not registered" case .apiCallCollectionNotRegistered(let type): return "The api call collection has not been registered for \(type)" + case .synchronizationInactive: + return "The synchronization is not active on this StoreCenter" } } diff --git a/LeStorage/StoreCenter.swift b/LeStorage/StoreCenter.swift index 52096aa..d7e3078 100644 --- a/LeStorage/StoreCenter.swift +++ b/LeStorage/StoreCenter.swift @@ -71,6 +71,7 @@ public class StoreCenter { init(directoryName: String? = nil) { self.directoryName = directoryName ?? "storage" + self._createDirectory() self._setupNotifications() @@ -89,10 +90,11 @@ public class StoreCenter { // Logger.log("device Id = \(self.deviceId())") } - public func configureURLs(secureScheme: Bool, domain: String, webSockets: Bool = true) { + public func configureURLs(secureScheme: Bool, domain: String, webSockets: Bool = true, useSynchronization: Bool = false) { self.useWebsockets = webSockets - + self.useSynchronization = useSynchronization + let urlManager: URLManager = URLManager(secureScheme: secureScheme, domain: domain) self._urlManager = urlManager self._services = Services(storeCenter: self, url: urlManager.api) @@ -629,15 +631,15 @@ public class StoreCenter { } /// Processes the data coming from a sync request - @MainActor func synchronizeContent(_ syncData: SyncData) { + @MainActor func synchronizeContent(_ syncData: SyncData) async { self._syncAddOrUpdate(syncData.updates) - self._syncDelete(syncData.deletions) + await self._syncDelete(syncData.deletions) self._syncAddOrUpdate(syncData.grants, shared: true) - self.syncRevoke(syncData.revocations, parents: syncData.revocationParents) + await self.syncRevoke(syncData.revocations, parents: syncData.revocationParents) self._syncAddOrUpdate(syncData.relationshipSets) - self._syncDelete(syncData.relationshipRemovals) - self._syncAddOrUpdate(syncData.sharedRelationshipSets) + await self._syncDelete(syncData.relationshipRemovals) + self._syncAddOrUpdate(syncData.sharedRelationshipSets, shared: true) self._syncRevoke(syncData.sharedRelationshipRemovals) Logger.log("sync content: updates = \(syncData.updates.count) / deletions = \(syncData.deletions.count), grants = \(syncData.grants.count)") @@ -670,23 +672,23 @@ public class StoreCenter { } /// Processes data that should be deleted inside the app - fileprivate func _syncDelete(_ deletionArrays: [ObjectIdentifierArray]) { + fileprivate func _syncDelete(_ deletionArrays: [ObjectIdentifierArray]) async { for deletionArray in deletionArrays { for deletedObject in deletionArray.items { - self.synchronizationDelete(id: deletedObject.modelId, type: deletionArray.type, storeId: deletedObject.storeId) + await self.synchronizationDelete(id: deletedObject.modelId, type: deletionArray.type, storeId: deletedObject.storeId) } } } /// Processes data that has been revoked - fileprivate func syncRevoke(_ revokedArrays: [ObjectIdentifierArray], parents: [[ObjectIdentifierArray]]) { + fileprivate func syncRevoke(_ revokedArrays: [ObjectIdentifierArray], parents: [[ObjectIdentifierArray]]) async { self._syncRevoke(revokedArrays) for revokedArray in revokedArrays { for revoked in revokedArray.items { - self.synchronizationDelete(id: revoked.modelId, type: revokedArray.type, storeId: revoked.storeId) // or synchronizationRevoke ? + await self.synchronizationDelete(id: revoked.modelId, type: revokedArray.type, storeId: revoked.storeId) // or synchronizationRevoke ? } } @@ -752,17 +754,14 @@ public class StoreCenter { } /// Deletes an instance with the given parameters + @MainActor func synchronizationDelete(id: String, type: T.Type, storeId: String?) { - - DispatchQueue.main.async { - do { -// let type = try self.classFromName(model) - try self._store(id: storeId).deleteNoSync(type: type, id: id) - } catch { - Logger.error(error) - } - self._cleanupDataLog(dataId: id) + do { + try self._store(id: storeId).deleteNoSync(type: type, id: id) + } catch { + Logger.error(error) } + self._cleanupDataLog(dataId: id) } /// Revokes a data that has been shared with the user @@ -1033,7 +1032,7 @@ public class StoreCenter { public func setAuthorizedUsersAsync(for instance: T, users: [String]) async throws { guard let dataAccessCollection = self._dataAccess else { - return + throw StoreError.synchronizationInactive } guard let userId = self.userId else { throw LeStorageError.cantCreateDataAccessBecauseUserIdIsNil diff --git a/LeStorage/SyncedCollection.swift b/LeStorage/SyncedCollection.swift index a87709c..c0b6e17 100644 --- a/LeStorage/SyncedCollection.swift +++ b/LeStorage/SyncedCollection.swift @@ -236,7 +236,7 @@ public class SyncedCollection: BaseCollection, SomeSynced self.setChanged() } self._deleteNoWrite(instance: instance) - Task { await self._executeBatchOnce(OperationBatch(delete: instance)) } + await self._executeBatchOnce(OperationBatch(delete: instance)) } /// Deletes an instance and writes