Fixes crash

multistore
Laurent 2 years ago
parent 93516188c5
commit e1f004d80a
  1. 2
      LeStorage/Store.swift
  2. 77
      LeStorage/StoredCollection.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!)
}
}

@ -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<T : Storable> : 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<T : Storable> : 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<T : Storable> : 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<T>) {
public func append(contentOfs sequence: any Sequence<T>) 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<T : Storable> : 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<T>? {
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,23 +277,24 @@ public class StoredCollection<T : Storable> : RandomAccessCollection, SomeCollec
return ApiCall(url: url, method: method.rawValue, dataId: String(instance.id), body: jsonString)
}
fileprivate func _prepareCall(apiCall: ApiCall<T>) {
fileprivate func _prepareCall(apiCall: ApiCall<T>) 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
}
if let apiCall = try self._callForInstance(instance, method: Method.post) {
try self._prepareCall(apiCall: apiCall)
Task {
do {
if let apiCall = try self._callForInstance(instance, method: Method.post) {
self._prepareCall(apiCall: apiCall)
_ = try await self._store.execute(apiCall: apiCall)
}
} catch {
self.rescheduleApiCallsIfNecessary()
Logger.error(error)
@ -299,43 +303,55 @@ public class StoredCollection<T : Storable> : RandomAccessCollection, SomeCollec
}
}
/// 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
}
if let apiCall = try self._callForInstance(instance, method: Method.put) {
try self._prepareCall(apiCall: apiCall)
Task {
do {
if let apiCall = try self._callForInstance(instance, method: Method.put) {
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()
}
}
}
// 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
}
if let apiCall = try self._callForInstance(instance, method: Method.delete) {
try self._prepareCall(apiCall: apiCall)
Task {
do {
if let apiCall = try self._callForInstance(instance, method: Method.delete) {
self._prepareCall(apiCall: apiCall)
_ = try await self._store.execute(apiCall: apiCall)
}
// let _ = try await self._store.service?.delete(instance)
} catch {
Logger.error(error)
self.rescheduleApiCallsIfNecessary()
@ -344,6 +360,9 @@ public class StoredCollection<T : Storable> : RandomAccessCollection, SomeCollec
}
}
// MARK: - Reschedule calls
/// number of time an execution loop has been called
@ -422,8 +441,8 @@ public class StoredCollection<T : Storable> : RandomAccessCollection, SomeCollec
}
}
public func append(_ newElement: T) {
self.addOrUpdate(instance: newElement)
}
// public func append(_ newElement: T) {
// self.addOrUpdate(instance: newElement)
// }
}

Loading…
Cancel
Save