diff --git a/LeStorage/ApiCallCollection.swift b/LeStorage/ApiCallCollection.swift index 519e7c4..6733c06 100644 --- a/LeStorage/ApiCallCollection.swift +++ b/LeStorage/ApiCallCollection.swift @@ -170,13 +170,13 @@ actor ApiCallCollection: SomeCallCollection { func rescheduleApiCallsIfNecessary() { if self.items.isNotEmpty && !self._isRescheduling { self._schedulingTask = Task { - await self._rescheduleApiCalls() + await self._waitAndExecuteApiCalls() } } } /// Reschedule the execution of API calls - fileprivate func _rescheduleApiCalls() async { + fileprivate func _waitAndExecuteApiCalls() async { // Logger.log("\(T.resourceName()) > RESCHED") guard !self._isRescheduling, StoreCenter.main.collectionsCanSynchronize else { return } @@ -199,7 +199,6 @@ actor ApiCallCollection: SomeCallCollection { if T.copyServerResponse { StoreCenter.main.updateLocalInstances(results) } -// self._attemptLoops = -1 } } catch { Logger.error(error) @@ -208,7 +207,7 @@ actor ApiCallCollection: SomeCallCollection { self._isRescheduling = false if self.items.isNotEmpty { - await self._rescheduleApiCalls() + await self._waitAndExecuteApiCalls() } // Logger.log("\(T.resourceName()) > isRescheduling = \(self._isRescheduling)") @@ -218,7 +217,7 @@ actor ApiCallCollection: SomeCallCollection { fileprivate func _wait() async { #if DEBUG - let seconds = 2 * self._attemptLoops + let seconds = self._attemptLoops #else let delay = pow(2, self._attemptLoops) let seconds = NSDecimalNumber(decimal: delay).intValue @@ -236,10 +235,10 @@ actor ApiCallCollection: SomeCallCollection { /// Returns an APICall instance for the Storable [instance] and an HTTP [method] /// The method updates existing calls or creates a new one - fileprivate func _call(method: HTTPMethod, instance: T? = nil) throws -> ApiCall? { + fileprivate func _call(method: HTTPMethod, instance: T? = nil) async throws -> ApiCall? { if let instance { - return try self._callForInstance(method, instance: instance) + return try await self._callForInstance(method, instance: instance) } else { if self.items.contains(where: { $0.method == .get }) { return nil @@ -249,7 +248,7 @@ actor ApiCallCollection: SomeCallCollection { } } - fileprivate func _callForInstance(_ method: HTTPMethod, instance: T) throws -> ApiCall? { + fileprivate func _callForInstance(_ method: HTTPMethod, instance: T) async throws -> ApiCall? { if let existingCall = self.items.first(where: { $0.dataId == instance.stringId }) { switch method { @@ -322,10 +321,8 @@ actor ApiCallCollection: SomeCallCollection { /// Initiates the process of sending the data with the server fileprivate func _sendServerRequest(_ method: HTTPMethod, instance: T? = nil) async throws -> V? { - if let apiCall = try self._call(method: method, instance: instance) { + if let apiCall = try await self._call(method: method, instance: instance) { return try await self._prepareAndSendCall(apiCall) -// try self._prepareCall(apiCall: apiCall) -// return try await self._executeApiCall(apiCall) } else { return nil } diff --git a/LeStorage/Codables/GetSyncData.swift b/LeStorage/Codables/GetSyncData.swift index c2de254..c447a87 100644 --- a/LeStorage/Codables/GetSyncData.swift +++ b/LeStorage/Codables/GetSyncData.swift @@ -9,25 +9,26 @@ import Foundation class GetSyncData: SyncedModelObject, SyncedStorable, URLParameterConvertible { + var date: String = "" + static func tokenExemptedMethods() -> [HTTPMethod] { return [] } static func resourceName() -> String { - return "data" + return "sync-requests" } func copy(from other: any Storable) { guard let getSyncData = other as? GetSyncData else { return } - self.lastUpdate = getSyncData.lastUpdate + self.date = getSyncData.date } func queryParameters() -> [String : String] { - return ["last_update" : self._formattedLastUpdate] + return ["last_update" : self._formattedLastUpdate, + "device_id" : StoreCenter.main.deviceId()] } fileprivate var _formattedLastUpdate: String { - let formattedDate = Date.iso8601FractionalFormatter.string(from: self.lastUpdate) - let encodedDate = - formattedDate.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" + let encodedDate = self.date.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed) ?? "" return encodedDate.replacingOccurrences(of: "+", with: "%2B") } diff --git a/LeStorage/Codables/Settings.swift b/LeStorage/Codables/Settings.swift index cf35de2..74df14f 100644 --- a/LeStorage/Codables/Settings.swift +++ b/LeStorage/Codables/Settings.swift @@ -16,6 +16,6 @@ class Settings: MicroStorable { var userId: String? = nil var username: String? = nil var deviceId: String? = nil - var lastSynchronization: Date = Date() + var lastSynchronization: String = "2000-01-01T00:00:00.000000Z" } diff --git a/LeStorage/Services.swift b/LeStorage/Services.swift index 0ff3183..7ea78ad 100644 --- a/LeStorage/Services.swift +++ b/LeStorage/Services.swift @@ -271,7 +271,7 @@ public class Services { // print("sync POST \(String(describing: T.self)) => \(String(data: task.0, encoding: .utf8) ?? "")") var rescheduleApiCalls: Bool = false - var success: [T] = [] + var successes: [T] = [] if let response = task.1 as? HTTPURLResponse { let statusCode = response.statusCode @@ -285,11 +285,14 @@ public class Services { switch result.status { case 200..<300: if let data = result.data { - success.append(data) + successes.append(data) } try await StoreCenter.main.deleteApiCallById(type: T.self, id: result.apiCallId) default: + if let message = result.message { + print(message) + } rescheduleApiCalls = true } } @@ -321,7 +324,7 @@ public class Services { try? await StoreCenter.main.rescheduleApiCalls(type: T.self) } - return success + return successes } /// Returns the URLRequest for an ApiCall @@ -596,7 +599,7 @@ public class Services { let user: U = try await self._runRequest(postRequest) // StoreCenter.main.setUserUUID(uuidString: user.id) // StoreCenter.main.setUserName(user.username) - StoreCenter.main.userDidLog(user: user, date: loggingDate) + StoreCenter.main.userDidLogIn(user: user, at: loggingDate) return user } diff --git a/LeStorage/StoreCenter.swift b/LeStorage/StoreCenter.swift index 6154cd7..a2f726a 100644 --- a/LeStorage/StoreCenter.swift +++ b/LeStorage/StoreCenter.swift @@ -66,7 +66,7 @@ public class StoreCenter { self._resumeApiCalls() // self._configureWebSocket() } - Logger.log("device Id = \(self.deviceId())") +// Logger.log("device Id = \(self.deviceId())") } public func configureURLs(secureScheme: Bool, domain: String) { @@ -173,11 +173,15 @@ public class StoreCenter { // MARK: - Settings /// Sets the user info given a user - func userDidLog(user: UserBase, date: Date) { + func userDidLogIn(user: UserBase, at date: Date) { self._settingsStorage.update { settings in settings.userId = user.id settings.username = user.username - settings.lastSynchronization = date + + let date = Date.microSecondFormatter.string(from: date) + Logger.log("LOG date = \(date)") + + settings.lastSynchronization = Date.microSecondFormatter.string(from: Date.distantPast) self._configureWebSocket() } } @@ -210,7 +214,7 @@ public class StoreCenter { self._settingsStorage.update { settings in settings.username = nil settings.userId = nil - settings.lastSynchronization = Date() + settings.lastSynchronization = Date.microSecondFormatter.string(from: Date()) self._webSocketManager = nil } @@ -467,7 +471,7 @@ public class StoreCenter { await syncGetCollection.rescheduleImmediately() } else { let getSyncData = GetSyncData() - getSyncData.lastUpdate = lastSync + getSyncData.date = lastSync try await syncGetCollection.sendGetRequest(instance: getSyncData) } @@ -517,11 +521,10 @@ public class StoreCenter { try self._parseSyncRevocations(revocations, parents: json["revocation_parents"] as? [[String: Any]]) } - if let dateString = json["date"] as? String, - let date = Date.iso8601FractionalFormatter.date(from: dateString) { - Logger.log("Sets sync date = \(date)") + if let dateString = json["date"] as? String { + Logger.log("Sets sync date = \(dateString)") self._settingsStorage.update { settings in - settings.lastSynchronization = date + settings.lastSynchronization = dateString } } @@ -546,7 +549,7 @@ public class StoreCenter { Logger.w("Invalid update data for \(className)") continue } -// Logger.log(">>> UPDATE \(updateArray.count) \(className)") + Logger.log(">>> UPDATE \(updateArray.count) \(className)") let type = try StoreCenter.classFromName(className) diff --git a/LeStorage/StoredCollection+Sync.swift b/LeStorage/StoredCollection+Sync.swift index fbd6200..47e9fa5 100644 --- a/LeStorage/StoredCollection+Sync.swift +++ b/LeStorage/StoredCollection+Sync.swift @@ -276,7 +276,7 @@ extension StoredCollection: SomeSyncedCollection where T : SyncedStorable { if instance.lastUpdate > localInstance.lastUpdate { self.updateItem(instance, index: index) } else { - Logger.log("do not update: \(instance.lastUpdate.timeIntervalSince1970) / local: \(localInstance.lastUpdate.timeIntervalSince1970)") + print("do not update \(T.resourceName()): \(instance.lastUpdate.timeIntervalSince1970) / local: \(localInstance.lastUpdate.timeIntervalSince1970)") } } else { // insert if shared { diff --git a/LeStorage/Utils/Date+Extensions.swift b/LeStorage/Utils/Date+Extensions.swift index 7c4a10c..c3d81e6 100644 --- a/LeStorage/Utils/Date+Extensions.swift +++ b/LeStorage/Utils/Date+Extensions.swift @@ -23,4 +23,11 @@ extension Date { return iso8601Formatter } + public static var microSecondFormatter: DateFormatter = { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS'Z'" // puts 000 for the last decimals + formatter.timeZone = TimeZone(abbreviation: "UTC") + return formatter + }() + } diff --git a/LeStorage/WebSocketManager.swift b/LeStorage/WebSocketManager.swift index bdc2053..fb70460 100644 --- a/LeStorage/WebSocketManager.swift +++ b/LeStorage/WebSocketManager.swift @@ -61,7 +61,7 @@ class WebSocketManager: ObservableObject { self._failure = false switch message { case .string(let deviceId): - print("device id = \(StoreCenter.main.deviceId()), origin id: \(deviceId)") +// print("device id = \(StoreCenter.main.deviceId()), origin id: \(deviceId)") guard StoreCenter.main.deviceId() != deviceId else { break }