From e1f004d80aeb9ff4aba3ed6e3e1ef9c97cac4dd6 Mon Sep 17 00:00:00 2001 From: Laurent Date: Tue, 13 Feb 2024 11:19:57 +0100 Subject: [PATCH] Fixes crash --- LeStorage/Store.swift | 2 +- LeStorage/StoredCollection.swift | 101 ++++++++++++++++++------------- 2 files changed, 61 insertions(+), 42 deletions(-) diff --git a/LeStorage/Store.swift b/LeStorage/Store.swift index b467d04..214eb9e 100644 --- a/LeStorage/Store.swift +++ b/LeStorage/Store.swift @@ -142,7 +142,7 @@ public class Store { performedMigration = MigrationHistory(version: migration.version, resourceName: migration.resourceName) } - self._migrationCollection.addOrUpdate(instance: performedMigration!) + try self._migrationCollection.addOrUpdate(instance: performedMigration!) } } diff --git a/LeStorage/StoredCollection.swift b/LeStorage/StoredCollection.swift index f90ab3c..db263d3 100644 --- a/LeStorage/StoredCollection.swift +++ b/LeStorage/StoredCollection.swift @@ -9,6 +9,7 @@ import Foundation enum StoredCollectionError : Error { case unmanagedHTTPMethod(method: String) + case missingApiCallCollection } protocol SomeCollection : Identifiable { @@ -143,7 +144,7 @@ public class StoredCollection : RandomAccessCollection, SomeCollec /// Adds or updates the provided instance inside the collection /// Adds it if its id is not found, and otherwise updates it - public func addOrUpdate(instance: T) { + public func addOrUpdate(instance: T) throws { defer { self._hasChanged = true @@ -152,11 +153,11 @@ public class StoredCollection : RandomAccessCollection, SomeCollec // update if let index = self.items.firstIndex(where: { $0.id == instance.id }) { self.items[index] = instance - self._sendUpdateIfNecessary(instance) + try self._sendUpdateIfNecessary(instance) } else { // insert self.items.append(instance) self._index?[instance.stringId] = instance - self._sendInsertionIfNecessary(instance) + try self._sendInsertionIfNecessary(instance) } } @@ -171,18 +172,18 @@ public class StoredCollection : RandomAccessCollection, SomeCollec try instance.deleteDependencies() self.items.removeAll { $0.id == instance.id } self._index?.removeValue(forKey: instance.stringId) - self._sendDeletionIfNecessary(instance) + try self._sendDeletionIfNecessary(instance) } /// Inserts the whole sequence into the items array, no updates - public func append(contentOfs sequence: any Sequence) { + public func append(contentOfs sequence: any Sequence) throws { defer { self._hasChanged = true } self.items.append(contentsOf: sequence) for instance in sequence { - self._sendUpdateIfNecessary(instance) + try self._sendInsertionIfNecessary(instance) } } @@ -233,19 +234,21 @@ public class StoredCollection : RandomAccessCollection, SomeCollec /// Writes all the items as a json array inside a file fileprivate func _write() { + Logger.log("Start write...") do { let jsonString: String = try self.items.jsonString() let _ = try FileUtils.writeToDocumentDirectory(content: jsonString, fileName: T.fileName()) } catch { Logger.error(error) // TODO how to notify the main project } + Logger.log("End write") } // MARK: - Synchronization fileprivate func _callForInstance(_ instance: T, method: Method) throws -> ApiCall? { guard let apiCallCollection = self.apiCallsCollection else { - throw StoreError.apiCallCollectionNotRegistered(type: T.resourceName()) + throw StoredCollectionError.missingApiCallCollection } if let existingCall = apiCallCollection.first(where: { $0.dataId == instance.id }) { @@ -274,74 +277,90 @@ public class StoredCollection : RandomAccessCollection, SomeCollec return ApiCall(url: url, method: method.rawValue, dataId: String(instance.id), body: jsonString) } - fileprivate func _prepareCall(apiCall: ApiCall) { + fileprivate func _prepareCall(apiCall: ApiCall) throws { apiCall.lastAttemptDate = Date() apiCall.attemptsCount += 1 - self.apiCallsCollection?.addOrUpdate(instance: apiCall) + try self.apiCallsCollection?.addOrUpdate(instance: apiCall) } /// Sends an insert api call for the provided [instance] - fileprivate func _sendInsertionIfNecessary(_ instance: T) { + fileprivate func _sendInsertionIfNecessary(_ instance: T) throws { guard self.synchronized else { return } - Task { - do { - if let apiCall = try self._callForInstance(instance, method: Method.post) { - self._prepareCall(apiCall: apiCall) + + if let apiCall = try self._callForInstance(instance, method: Method.post) { + try self._prepareCall(apiCall: apiCall) + + Task { + do { _ = try await self._store.execute(apiCall: apiCall) + } catch { + self.rescheduleApiCallsIfNecessary() + Logger.error(error) } - } catch { - self.rescheduleApiCallsIfNecessary() - Logger.error(error) } + } } /// Sends an update api call for the provided [instance] - fileprivate func _sendUpdateIfNecessary(_ instance: T) { + fileprivate func _sendUpdateIfNecessary(_ instance: T) throws { guard self.synchronized else { return } - Task { - do { - if let apiCall = try self._callForInstance(instance, method: Method.put) { - self._prepareCall(apiCall: apiCall) + if let apiCall = try self._callForInstance(instance, method: Method.put) { + try self._prepareCall(apiCall: apiCall) + Task { + do { _ = try await self._store.execute(apiCall: apiCall) + } catch { + Logger.error(error) + self.rescheduleApiCallsIfNecessary() } - -// let _ = try await self._store.service?.update(instance) - } catch { - Logger.error(error) - self.rescheduleApiCallsIfNecessary() } } + + + +// Task { +// do { +// if let apiCall = try self._callForInstance(instance, method: Method.put) { +// try self._prepareCall(apiCall: apiCall) +// _ = try await self._store.execute(apiCall: apiCall) +// } +// +//// let _ = try await self._store.service?.update(instance) +// } catch { +// Logger.error(error) +// self.rescheduleApiCallsIfNecessary() +// } +// } } /// Sends an delete api call for the provided [instance] - fileprivate func _sendDeletionIfNecessary(_ instance: T) { + fileprivate func _sendDeletionIfNecessary(_ instance: T) throws { guard self.synchronized else { return } - Task { - do { - - if let apiCall = try self._callForInstance(instance, method: Method.delete) { - self._prepareCall(apiCall: apiCall) + if let apiCall = try self._callForInstance(instance, method: Method.delete) { + try self._prepareCall(apiCall: apiCall) + Task { + do { _ = try await self._store.execute(apiCall: apiCall) + } catch { + Logger.error(error) + self.rescheduleApiCallsIfNecessary() } - -// let _ = try await self._store.service?.delete(instance) - } catch { - Logger.error(error) - self.rescheduleApiCallsIfNecessary() } + } + } // MARK: - Reschedule calls @@ -422,8 +441,8 @@ public class StoredCollection : RandomAccessCollection, SomeCollec } } - public func append(_ newElement: T) { - self.addOrUpdate(instance: newElement) - } +// public func append(_ newElement: T) { +// self.addOrUpdate(instance: newElement) +// } }