|
|
|
|
@ -40,10 +40,6 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// func loadDataFromServerIfAllowed() async throws { |
|
|
|
|
// try await self.loadDataFromServerIfAllowed(clear: false) |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
/// Retrieves the data from the server and loads it into the items array |
|
|
|
|
public func loadDataFromServerIfAllowed(clear: Bool = false) async throws { |
|
|
|
|
do { |
|
|
|
|
@ -67,13 +63,25 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
DispatchQueue.main.async { |
|
|
|
|
Task { |
|
|
|
|
await _updateLocalInstance(serverInstance) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// DispatchQueue.main.async { |
|
|
|
|
// if let localInstance = self.findById(serverInstance.id) { |
|
|
|
|
// localInstance.copy(from: serverInstance) |
|
|
|
|
// self.setChanged() |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@MainActor |
|
|
|
|
fileprivate func _updateLocalInstance(_ serverInstance: T) { |
|
|
|
|
if let localInstance = self.findById(serverInstance.id) { |
|
|
|
|
localInstance.copy(from: serverInstance) |
|
|
|
|
self.setChanged() |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@MainActor |
|
|
|
|
func loadItems(_ items: [T], clear: Bool = false) { |
|
|
|
|
@ -89,17 +97,6 @@ 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 throws { |
|
|
|
|
if let result = _addOrUpdateCore(instance: instance) { |
|
|
|
|
if result.isNewItem { |
|
|
|
|
try await self._executeBatchOnce(OperationBatch(insert: result.item)) |
|
|
|
|
} else { |
|
|
|
|
try await self._executeBatchOnce(OperationBatch(update: result.item)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Adds or update an instance synchronously, dispatching network operations to background tasks |
|
|
|
|
public override func addOrUpdate(instance: T) { |
|
|
|
|
if let result = _addOrUpdateCore(instance: instance) { |
|
|
|
|
@ -128,37 +125,6 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced |
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// func addOrUpdateAsync(instance: T) async { |
|
|
|
|
// instance.lastUpdate = Date() |
|
|
|
|
// if let index = self.items.firstIndex(where: { $0.id == instance.id }) { |
|
|
|
|
// if self.updateItem(instance, index: index, shouldBeSynchronized: true) { |
|
|
|
|
// await self._sendUpdate(instance) |
|
|
|
|
// self.setChanged() |
|
|
|
|
// } |
|
|
|
|
// } else { |
|
|
|
|
// if self.addItem(instance: instance, shouldBeSynchronized: true) { |
|
|
|
|
// await self._sendInsertion(instance) |
|
|
|
|
// self.setChanged() |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// |
|
|
|
|
// /// Adds or update an instance and writes |
|
|
|
|
// public override func addOrUpdate(instance: T) { |
|
|
|
|
// instance.lastUpdate = Date() |
|
|
|
|
// if let index = self.items.firstIndex(where: { $0.id == instance.id }) { |
|
|
|
|
// if self.updateItem(instance, index: index, shouldBeSynchronized: true) { |
|
|
|
|
// Task { await self._sendUpdate(instance) } |
|
|
|
|
// self.setChanged() |
|
|
|
|
// } |
|
|
|
|
// } else { |
|
|
|
|
// if self.addItem(instance: instance, shouldBeSynchronized: true) { |
|
|
|
|
// Task { await self._sendInsertion(instance) } |
|
|
|
|
// self.setChanged() |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
fileprivate func _addOrUpdateCore(contentOfs sequence: any Sequence<T>) -> OperationBatch<T> { |
|
|
|
|
|
|
|
|
|
defer { |
|
|
|
|
@ -190,11 +156,6 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced |
|
|
|
|
Task { await self._sendOperationBatch(batch) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func addOrUpdateAsync(contentOfs sequence: any Sequence<T>) async throws { |
|
|
|
|
let batch = self._addOrUpdateCore(contentOfs: sequence) |
|
|
|
|
try await self._executeBatchOnce(batch) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Proceeds to delete all instance of the collection, properly cleaning up dependencies and sending API calls |
|
|
|
|
override public func deleteAll() throws { |
|
|
|
|
self.delete(contentOfs: self.items) |
|
|
|
|
@ -228,37 +189,23 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced |
|
|
|
|
Task { await self._sendOperationBatch(batch) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// 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 throws{ |
|
|
|
|
guard sequence.isNotEmpty else { return } |
|
|
|
|
let batch = self._deleteCore(contentOfs: sequence) |
|
|
|
|
try await self._executeBatchOnce(batch) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Deletes an instance and writes |
|
|
|
|
func deleteAsync(instance: T) async throws{ |
|
|
|
|
defer { |
|
|
|
|
self.setChanged() |
|
|
|
|
} |
|
|
|
|
self._deleteNoWrite(instance: instance) |
|
|
|
|
try await self._executeBatchOnce(OperationBatch(delete: instance)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Deletes an instance and writes |
|
|
|
|
override public func delete(instance: T) { |
|
|
|
|
defer { |
|
|
|
|
self.setChanged() |
|
|
|
|
} |
|
|
|
|
self._deleteNoWrite(instance: instance) |
|
|
|
|
self.deleteItem(instance, shouldBeSynchronized: true) |
|
|
|
|
self.storeCenter.createDeleteLog(instance) |
|
|
|
|
|
|
|
|
|
Task { await self._sendDeletion(instance) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Deletes an instance without writing, logs the operation and sends an API call |
|
|
|
|
fileprivate func _deleteNoWrite(instance: T) { |
|
|
|
|
self.deleteItem(instance, shouldBeSynchronized: true) |
|
|
|
|
self.storeCenter.createDeleteLog(instance) |
|
|
|
|
// await self._sendDeletion(instance) |
|
|
|
|
} |
|
|
|
|
// fileprivate func _deleteNoWrite(instance: T) { |
|
|
|
|
// self.deleteItem(instance, shouldBeSynchronized: true) |
|
|
|
|
// self.storeCenter.createDeleteLog(instance) |
|
|
|
|
//// await self._sendDeletion(instance) |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
public func deleteDependencies(_ items: any RandomAccessCollection<T>, shouldBeSynchronized: Bool) { |
|
|
|
|
guard items.isNotEmpty else { return } |
|
|
|
|
@ -269,6 +216,57 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public override func deleteDependencies(_ items: any Sequence<T>) { |
|
|
|
|
super.deleteDependencies(items) |
|
|
|
|
|
|
|
|
|
let batch = OperationBatch<T>() |
|
|
|
|
batch.deletes = Array(items) |
|
|
|
|
Task { await self._sendOperationBatch(batch) } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public func deleteDependenciesAsync(_ items: any Sequence<T>) async { |
|
|
|
|
super.deleteDependencies(items) |
|
|
|
|
|
|
|
|
|
let batch = OperationBatch<T>() |
|
|
|
|
batch.deletes = Array(items) |
|
|
|
|
await self._sendOperationBatch(batch) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// MARK: - Asynchronous operations |
|
|
|
|
|
|
|
|
|
/// Adds or update an instance asynchronously and waits for network operations |
|
|
|
|
func addOrUpdateAsync(instance: T) async throws { |
|
|
|
|
if let result = _addOrUpdateCore(instance: instance) { |
|
|
|
|
if result.isNewItem { |
|
|
|
|
try await self._executeBatchOnce(OperationBatch(insert: result.item)) |
|
|
|
|
} else { |
|
|
|
|
try await self._executeBatchOnce(OperationBatch(update: result.item)) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func addOrUpdateAsync(contentOfs sequence: any Sequence<T>) async throws { |
|
|
|
|
let batch = self._addOrUpdateCore(contentOfs: sequence) |
|
|
|
|
try await self._executeBatchOnce(batch) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// 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 throws{ |
|
|
|
|
guard sequence.isNotEmpty else { return } |
|
|
|
|
let batch = self._deleteCore(contentOfs: sequence) |
|
|
|
|
try await self._executeBatchOnce(batch) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Deletes an instance and writes |
|
|
|
|
func deleteAsync(instance: T) async throws { |
|
|
|
|
defer { |
|
|
|
|
self.setChanged() |
|
|
|
|
} |
|
|
|
|
self.deleteItem(instance, shouldBeSynchronized: true) |
|
|
|
|
self.storeCenter.createDeleteLog(instance) |
|
|
|
|
try await self._executeBatchOnce(OperationBatch(delete: instance)) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// MARK: - Basic operations without sync |
|
|
|
|
|
|
|
|
|
/// Adds or update an instance without synchronizing it |
|
|
|
|
@ -350,49 +348,6 @@ public class SyncedCollection<T : SyncedStorable>: BaseCollection<T>, SomeSynced |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Sends an insert api call for the provided |
|
|
|
|
/// Calls copyFromServerInstance on the instance with the result of the HTTP call |
|
|
|
|
/// - Parameters: |
|
|
|
|
/// - instance: the object to POST |
|
|
|
|
// fileprivate func _sendInsertionIfNecessary(_ instance: T) { |
|
|
|
|
// |
|
|
|
|
// Task { |
|
|
|
|
// do { |
|
|
|
|
// if let result = try await self.store.sendInsertion(instance) { |
|
|
|
|
// self.updateFromServerInstance(result) |
|
|
|
|
// } |
|
|
|
|
// } catch { |
|
|
|
|
// Logger.error(error) |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// |
|
|
|
|
// /// Sends an update api call for the provided [instance] |
|
|
|
|
// /// - Parameters: |
|
|
|
|
// /// - instance: the object to PUT |
|
|
|
|
// fileprivate func _sendUpdateIfNecessary(_ instance: T) { |
|
|
|
|
// Task { |
|
|
|
|
// do { |
|
|
|
|
// try await self.store.sendUpdate(instance) |
|
|
|
|
// } catch { |
|
|
|
|
// Logger.error(error) |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// |
|
|
|
|
// /// Sends an delete api call for the provided [instance] |
|
|
|
|
// /// - Parameters: |
|
|
|
|
// /// - instance: the object to DELETE |
|
|
|
|
// fileprivate func _sendDeletionIfNecessary(_ instance: T) { |
|
|
|
|
// Task { |
|
|
|
|
// do { |
|
|
|
|
// try await self.store.sendDeletion(instance) |
|
|
|
|
// } catch { |
|
|
|
|
// Logger.error(error) |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
// MARK: - Synchronization |
|
|
|
|
|
|
|
|
|
/// Adds or update an instance if it is newer than the local instance |
|
|
|
|
|