Fixes and improvements

sync3
Laurent 6 months ago
parent fb6999a66c
commit 775bed665b
  1. 16
      LeStorage/Codables/SyncData.swift
  2. 6
      LeStorage/Services.swift
  3. 22
      LeStorage/StoreCenter.swift
  4. 31
      LeStorage/SyncedCollection.swift

@ -28,8 +28,8 @@ class SyncData {
var grants: [SyncedStorableArray] = []
var revocations: [ObjectIdentifierArray] = []
var revocationParents: [[ObjectIdentifierArray]] = []
var relationshipSets: [SyncedStorableArray] = []
var relationshipRemovals: [ObjectIdentifierArray] = []
// var relationshipSets: [SyncedStorableArray] = []
// var relationshipRemovals: [ObjectIdentifierArray] = []
var sharedRelationshipSets: [SyncedStorableArray] = []
var sharedRelationshipRemovals: [ObjectIdentifierArray] = []
var date: String?
@ -60,12 +60,12 @@ class SyncData {
}
}
if let relationshipSets = json["relationship_sets"] as? [String: Any] {
self.relationshipSets = try storeCenter.decodeDictionary(relationshipSets)
}
if let relationshipRemovals = json["relationship_removals"] as? [String: Any] {
self.relationshipRemovals = try storeCenter.decodeObjectIdentifierDictionary(relationshipRemovals)
}
// if let relationshipSets = json["relationship_sets"] as? [String: Any] {
// self.relationshipSets = try storeCenter.decodeDictionary(relationshipSets)
// }
// if let relationshipRemovals = json["relationship_removals"] as? [String: Any] {
// self.relationshipRemovals = try storeCenter.decodeObjectIdentifierDictionary(relationshipRemovals)
// }
if let sharedRelationshipSets = json["shared_relationship_sets"] as? [String: Any] {
self.sharedRelationshipSets = try storeCenter.decodeDictionary(sharedRelationshipSets)
}

@ -33,7 +33,7 @@ let changePasswordCall: ServiceCall = ServiceCall(
path: "change-password/", method: .put, requiresToken: true)
let postDeviceTokenCall: ServiceCall = ServiceCall(
path: "device-token/", method: .post, requiresToken: true)
let getUserDataAccessCall: ServiceCall = ServiceCall(
let getUserDataAccessCallContent: ServiceCall = ServiceCall(
path: "data-access-content/", method: .get, requiresToken: true)
let userNamesCall: ServiceCall = ServiceCall(
path: "user-names/", method: .get, requiresToken: true)
@ -630,8 +630,8 @@ public class Services {
}
/// Returns the list of DataAccess
func getUserDataAccess() async throws {
let request = try self._baseRequest(call: getUserDataAccessCall)
func getUserDataAccessContent() async throws {
let request = try self._baseRequest(call: getUserDataAccessCallContent)
if let data = try await self._runRequest(request) {
await self.storeCenter.userDataAccessRetrieved(data)
}

@ -48,7 +48,7 @@ public class StoreCenter {
lazy fileprivate var _deleteLogs: StoredCollection<DataLog> = { self.mainStore.registerCollection() }()
/// A synchronized collection of DataAccess
fileprivate var _dataAccess: SyncedCollection<DataAccess>? = nil
fileprivate(set) var dataAccessCollection: SyncedCollection<DataAccess>? = nil
/// A collection storing FailedAPICall objects
fileprivate var _failedAPICallsCollection: SyncedCollection<FailedAPICall>? = nil
@ -101,7 +101,7 @@ public class StoreCenter {
self.tokenKeychain = KeychainStore(serverId: urlManager.api)
if self.useSynchronization {
self._dataAccess = self.mainStore.registerSynchronizedCollection()
self.dataAccessCollection = self.mainStore.registerSynchronizedCollection()
}
Logger.log("Sync URL: \(urlManager.api)")
@ -250,7 +250,7 @@ public class StoreCenter {
self._failedAPICallsCollection?.reset()
self._stores.removeAll()
self._dataAccess?.reset()
self.dataAccessCollection?.reset()
self._deleteLogs.reset()
self._settingsStorage.update { settings in
@ -557,7 +557,7 @@ public class StoreCenter {
if self.useSynchronization {
Task {
do {
try await self.service().getUserDataAccess()
try await self.service().getUserDataAccessContent()
} catch {
Logger.error(error)
}
@ -637,8 +637,8 @@ public class StoreCenter {
await self._syncDelete(syncData.deletions)
self._syncAddOrUpdate(syncData.grants, shared: true)
await self.syncRevoke(syncData.revocations, parents: syncData.revocationParents)
self._syncAddOrUpdate(syncData.relationshipSets)
await self._syncDelete(syncData.relationshipRemovals)
// self._syncAddOrUpdate(syncData.relationshipSets)
// await self._syncDelete(syncData.relationshipRemovals)
self._syncAddOrUpdate(syncData.sharedRelationshipSets, shared: true)
self._syncRevoke(syncData.sharedRelationshipRemovals)
@ -1020,7 +1020,7 @@ public class StoreCenter {
/// Returns the list of users have access to a data given its id
public func authorizedUsers(for modelId: String) -> [String] {
guard let dataAccessCollection = self._dataAccess else {
guard let dataAccessCollection = self.dataAccessCollection else {
return []
}
if let dataAccess = dataAccessCollection.first(where: { $0.modelId == modelId }) {
@ -1031,7 +1031,7 @@ public class StoreCenter {
public func setAuthorizedUsersAsync<T: SyncedStorable>(for instance: T, users: [String]) async throws {
guard let dataAccessCollection = self._dataAccess else {
guard let dataAccessCollection = self.dataAccessCollection else {
throw StoreError.synchronizationInactive
}
guard let userId = self.userId else {
@ -1040,15 +1040,15 @@ public class StoreCenter {
if let dataAccess = dataAccessCollection.first(where: { $0.modelId == instance.stringId }) {
if users.isEmpty {
await dataAccessCollection.deleteAsync(instance: dataAccess)
try await dataAccessCollection.deleteAsync(instance: dataAccess)
} else {
dataAccess.sharedWith.removeAll()
dataAccess.sharedWith = users
await dataAccessCollection.addOrUpdateAsync(instance: dataAccess)
try await dataAccessCollection.addOrUpdateAsync(instance: dataAccess)
}
} else {
let dataAccess = DataAccess(owner: userId, sharedWith: users, modelName: String(describing: type(of: instance)), modelId: instance.stringId)
await dataAccessCollection.addOrUpdateAsync(instance: dataAccess)
try await dataAccessCollection.addOrUpdateAsync(instance: dataAccess)
}
}

@ -53,6 +53,11 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced
}
}
func loadOnceAsync() async throws {
let items: [T] = try await self.storeCenter.service().get()
await self.loadItems(items, clear: true)
}
/// Updates a local item from a server instance. This method is typically used when the server makes update
/// to an object when it's inserted. The SyncedCollection possibly needs to update its own copy with new values.
/// - serverInstance: the instance of the object on the server
@ -85,12 +90,12 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced
// MARK: - Basic operations with sync
/// Adds or update an instance asynchronously and waits for network operations
func addOrUpdateAsync(instance: T) async {
func addOrUpdateAsync(instance: T) async throws {
if let result = _addOrUpdateCore(instance: instance) {
if result.isNewItem {
await self._executeBatchOnce(OperationBatch(insert: result.item))
try await self._executeBatchOnce(OperationBatch(insert: result.item))
} else {
await self._executeBatchOnce(OperationBatch(update: result.item))
try await self._executeBatchOnce(OperationBatch(update: result.item))
}
}
}
@ -185,9 +190,9 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced
Task { await self._sendOperationBatch(batch) }
}
func addOrUpdateAsync(contentOfs sequence: any Sequence<T>) async {
func addOrUpdateAsync(contentOfs sequence: any Sequence<T>) async throws {
let batch = self._addOrUpdateCore(contentOfs: sequence)
await self._executeBatchOnce(batch)
try await self._executeBatchOnce(batch)
}
/// Proceeds to delete all instance of the collection, properly cleaning up dependencies and sending API calls
@ -224,19 +229,19 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced
}
/// Deletes all items of the sequence by id and sets the collection as changed to trigger a write
public func deleteAsync(contentOfs sequence: any RandomAccessCollection<T>) async {
public func deleteAsync(contentOfs sequence: any RandomAccessCollection<T>) async throws{
guard sequence.isNotEmpty else { return }
let batch = self._deleteCore(contentOfs: sequence)
await self._executeBatchOnce(batch)
try await self._executeBatchOnce(batch)
}
/// Deletes an instance and writes
func deleteAsync(instance: T) async {
func deleteAsync(instance: T) async throws{
defer {
self.setChanged()
}
self._deleteNoWrite(instance: instance)
await self._executeBatchOnce(OperationBatch(delete: instance))
try await self._executeBatchOnce(OperationBatch(delete: instance))
}
/// Deletes an instance and writes
@ -327,12 +332,8 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced
}
}
fileprivate func _executeBatchOnce(_ batch: OperationBatch<T>) async {
do {
try await self.storeCenter.singleBatchExecution(batch)
} catch {
Logger.error(error)
}
fileprivate func _executeBatchOnce(_ batch: OperationBatch<T>) async throws {
try await self.storeCenter.singleBatchExecution(batch)
}
// MARK: Single calls

Loading…
Cancel
Save