Improves syncing

sync3
Laurent 5 months ago
parent 1f73660832
commit 572a2e9bec
  1. 2
      LeStorage/ApiCallCollection.swift
  2. 1
      LeStorage/Store.swift
  3. 42
      LeStorage/StoreCenter.swift
  4. 13
      LeStorage/StoredCollection.swift
  5. 7
      LeStorage/SyncedCollection.swift
  6. 1
      LeStorage/WebSocketManager.swift

@ -250,7 +250,7 @@ actor ApiCallCollection<T: SyncedStorable>: SomeCallCollection {
@discardableResult func _executeGetCall(apiCall: ApiCall<T>) async throws -> Data {
let data = try await self.storeCenter.executeGet(apiCall: apiCall)
Logger.log("GET received = \(T.resourceName())")
// Logger.log("GET received = \(T.resourceName())")
if T.self == GetSyncData.self {
let syncData = try SyncData(data: data, storeCenter: self.storeCenter)

@ -466,6 +466,7 @@ final public class Store {
var fileURL = try self._directoryPath()
fileURL.append(component: fileName)
try content.write(to: fileURL, atomically: false, encoding: .utf8)
Logger.log("write into \(fileURL)...")
}
/// Returns the URL matching a Storable type

@ -67,6 +67,9 @@ public class StoreCenter {
var useWebsockets: Bool = false
var useSynchronization: Bool = false
var synchronizesData: Bool = false
var wantsToSynchronize: Bool = false
init(directoryName: String? = nil) {
self.directoryName = directoryName ?? "storage"
@ -581,19 +584,35 @@ public class StoreCenter {
guard self.isAuthenticated else {
return
}
guard !self.synchronizesData else {
// Logger.log("*** blocked sync")
self.wantsToSynchronize = true
return
}
self.synchronizesData = true
self.wantsToSynchronize = false
let lastSync = self._settingsStorage.item.lastSynchronization
Logger.log("REQUEST sync: \(lastSync)")
let syncGetCollection: ApiCallCollection<GetSyncData> = try self.apiCallCollection()
if await syncGetCollection.hasPendingCalls() {
await syncGetCollection.rescheduleImmediately()
} else {
if await syncGetCollection.hasPendingCalls() == false {
Logger.log("*** START sync: \(lastSync)")
let getSyncData = GetSyncData()
getSyncData.date = lastSync
try await syncGetCollection.sendGetRequest(instance: getSyncData)
}
// if await syncGetCollection.hasPendingCalls() {
// await syncGetCollection.rescheduleImmediately()
// Logger.log("=> reschedule")
// } else {
// Logger.log("=> send GET")
// let getSyncData = GetSyncData()
// getSyncData.date = lastSync
// try await syncGetCollection.sendGetRequest(instance: getSyncData)
// }
}
@discardableResult func testSynchronizeOnceAsync() async throws -> Data {
@ -653,7 +672,7 @@ public class StoreCenter {
await self._syncAddOrUpdate(syncData.sharedRelationshipSets, shared: .granted)
await self._syncRevoke(syncData.sharedRelationshipRemovals)
Logger.log("sync content: updates = \(syncData.updates.count) / deletions = \(syncData.deletions.count), grants = \(syncData.grants.count)")
// Logger.log("sync content: updates = \(syncData.updates.count) / deletions = \(syncData.deletions.count), grants = \(syncData.grants.count)")
if let dateString = syncData.date {
Logger.log("Sets sync date = \(dateString)")
@ -662,6 +681,17 @@ public class StoreCenter {
}
}
self.synchronizesData = false
if self.wantsToSynchronize {
do {
try await self.synchronizeLastUpdates()
} catch {
Logger.error(error)
}
}
// Logger.log(">>> SYNC ENDED")
NotificationCenter.default.post(
name: NSNotification.Name.LeStorageDidSynchronize, object: self)
@ -924,7 +954,7 @@ public class StoreCenter {
Logger.w("Invalid update data for \(className)")
continue
}
Logger.log(">>> UPDATE \(array.count) \(className)")
// Logger.log(">>> UPDATE \(array.count) \(className)")
let type = try self.classFromName(className)
let decodedArray = try self._decodeArray(type: type, array: array)

@ -76,6 +76,8 @@ public class StoredCollection<T: Storable>: SomeCollection {
/// A PendingOperationManager instance that manages operations while the collection is not loaded
fileprivate(set) var pendingOperationManager: PendingOperationManager<T>? = nil
fileprivate var _writingTimer: Timer? = nil
/// Indicates whether the collection has changed, thus requiring a write operation
fileprivate var _triggerWrite: Bool = false {
didSet {
@ -499,12 +501,18 @@ public class StoredCollection<T: Storable>: SomeCollection {
/// Schedules a write operation
fileprivate func _scheduleWrite() {
DispatchQueue(label: "lestorage.queue.write", qos: .utility).asyncAndWait {
self._write()
self._cleanTimer()
self._writingTimer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(self._write), userInfo: nil, repeats: false)
}
}
fileprivate func _cleanTimer() {
self._writingTimer?.invalidate()
self._writingTimer = nil
}
/// Writes all the items as a json array inside a file
fileprivate func _write() {
@objc fileprivate func _write() {
do {
let jsonString: String = try self.items.jsonString()
try self.store.write(content: jsonString, fileName: T.fileName())
@ -513,6 +521,7 @@ public class StoredCollection<T: Storable>: SomeCollection {
self.storeCenter.log(
message: "write failed for \(T.resourceName()): \(error.localizedDescription)")
}
self._cleanTimer()
}
/// Simply clears the items of the collection

@ -332,10 +332,15 @@ public class SyncedCollection<T : SyncedStorable>: SomeSyncedCollection, Collect
// }
/// Deletes the instance in the collection without synchronization
func deleteNoSync(contentOfs sequence: any RandomAccessCollection<T>) {
public func deleteNoSync(contentOfs sequence: any RandomAccessCollection<T>) {
self.collection.delete(contentOfs: sequence)
}
/// Deletes the instance in the collection without synchronization
public func deleteNoSync(instance: T, cascading: Bool = false) {
self.collection.delete(instance: instance, actionOption: .cascade)
}
func deleteUnusedGranted(instance: T) {
guard instance.sharing != nil else { return }
self.deleteByStringId(instance.stringId)

@ -72,6 +72,7 @@ class WebSocketManager: ObservableObject {
Task {
do {
// Logger.log("Websocket notif, sync...")
try await self.storeCenter.synchronizeLastUpdates()
} catch {
Logger.error(error)

Loading…
Cancel
Save