Server inserts can now update data locally

multistore
Laurent 1 year ago
parent 9485654045
commit a8133b697c
  1. 4
      LeStorage/ModelObject.swift
  2. 5
      LeStorage/Storable.swift
  3. 85
      LeStorage/StoredCollection.swift

@ -15,5 +15,9 @@ open class ModelObject {
open func deleteDependencies() throws { open func deleteDependencies() throws {
} }
open func copyFromServerInstance(_ instance: any Storable) -> Bool {
return false
}
} }

@ -16,12 +16,15 @@ public protocol Storable: Codable, Identifiable where ID : StringProtocol {
/// Returns HTTP methods that do not need to pass the token to the request /// Returns HTTP methods that do not need to pass the token to the request
static func tokenExemptedMethods() -> [HTTPMethod] static func tokenExemptedMethods() -> [HTTPMethod]
/// A method that deletes the local dependencies of the resource /// A method that deletes the local dependencies of the resource
/// Mimics the behavior the cascading delete on the django server /// Mimics the behavior the cascading delete on the django server
/// Typically when we delete a resource, we automatically delete items that depends on it, /// Typically when we delete a resource, we automatically delete items that depends on it,
/// so when we do that on the server, we also need to do it locally /// so when we do that on the server, we also need to do it locally
func deleteDependencies() throws func deleteDependencies() throws
func copyFromServerInstance(_ instance: any Storable) -> Bool
} }
extension Storable { extension Storable {

@ -195,7 +195,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
do { do {
let items: [T] = try await self._store.getItems() let items: [T] = try await self._store.getItems()
try self._addOrUpdate(contentOfs: items, shouldSync: false) try self._addOrUpdate(contentOfs: items, shouldSync: false)
self._hasChanged = true // self._hasChanged = true
self.hasLoadedFromServer = true self.hasLoadedFromServer = true
NotificationCenter.default.post(name: NSNotification.Name.CollectionDidLoad, object: self) NotificationCenter.default.post(name: NSNotification.Name.CollectionDidLoad, object: self)
} catch { } catch {
@ -360,7 +360,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
/// Writes all the items as a json array inside a file /// Writes all the items as a json array inside a file
fileprivate func _write() { fileprivate func _write() {
Logger.log("Start write...") Logger.log("Start write to \(T.fileName())...")
do { do {
let jsonString: String = try self.items.jsonString() let jsonString: String = try self.items.jsonString()
try self._writeToStorageDirectory(content: jsonString, fileName: T.fileName()) try self._writeToStorageDirectory(content: jsonString, fileName: T.fileName())
@ -428,7 +428,6 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
/// Creates an API call for the Storable [instance] and an HTTP [method] /// Creates an API call for the Storable [instance] and an HTTP [method]
fileprivate func _createCall(_ instance: T, method: HTTPMethod) throws -> ApiCall<T> { fileprivate func _createCall(_ instance: T, method: HTTPMethod) throws -> ApiCall<T> {
// let baseURL = try _store.service().baseURL
let jsonString = try instance.jsonString() let jsonString = try instance.jsonString()
return ApiCall(method: method, dataId: String(instance.id), body: jsonString) return ApiCall(method: method, dataId: String(instance.id), body: jsonString)
} }
@ -446,20 +445,14 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
return return
} }
if let apiCall = try self._callForInstance(instance, method: HTTPMethod.post) { Task {
try self._prepareCall(apiCall: apiCall) do {
try await self._synchronize(instance, method: HTTPMethod.post)
Task { } catch {
do { self.rescheduleApiCallsIfNecessary()
_ = try await self._store.execute(apiCall: apiCall) Logger.error(error)
} catch {
self.rescheduleApiCallsIfNecessary()
Logger.error(error)
}
} }
} }
} }
/// Sends an update api call for the provided [instance] /// Sends an update api call for the provided [instance]
@ -467,19 +460,15 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
guard self.synchronized, self._sendsUpdate, Store.main.collectionsCanSynchronize else { guard self.synchronized, self._sendsUpdate, Store.main.collectionsCanSynchronize else {
return return
} }
Task {
if let apiCall = try self._callForInstance(instance, method: HTTPMethod.put) { do {
try self._prepareCall(apiCall: apiCall) try await self._synchronize(instance, method: HTTPMethod.put)
Task { } catch {
do { self.rescheduleApiCallsIfNecessary()
_ = try await self._store.execute(apiCall: apiCall) Logger.error(error)
} catch {
Logger.error(error)
self.rescheduleApiCallsIfNecessary()
}
} }
} }
} }
/// Sends an delete api call for the provided [instance] /// Sends an delete api call for the provided [instance]
@ -487,21 +476,37 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
guard self.synchronized, Store.main.collectionsCanSynchronize else { guard self.synchronized, Store.main.collectionsCanSynchronize else {
return return
} }
Task {
if let apiCall = try self._callForInstance(instance, method: HTTPMethod.delete) { do {
try await self._synchronize(instance, method: HTTPMethod.delete)
} catch {
self.rescheduleApiCallsIfNecessary()
Logger.error(error)
}
}
}
fileprivate func _synchronize(_ instance: T, method: HTTPMethod) async throws {
if let apiCall = try self._callForInstance(instance, method: method) {
try self._prepareCall(apiCall: apiCall) try self._prepareCall(apiCall: apiCall)
Task { try await self._executeApiCall(apiCall)
do { }
_ = try await self._store.execute(apiCall: apiCall) }
} catch {
Logger.error(error) fileprivate func _executeApiCall(_ apiCall: ApiCall<T>) async throws {
self.rescheduleApiCallsIfNecessary() let result = try await self._store.execute(apiCall: apiCall)
switch apiCall.method {
case .post:
// DispatchQueue.main.async {
if let instance = self.findById(result.stringId) {
self._hasChanged = instance.copyFromServerInstance(result)
} }
} // }
default:
break
} }
Logger.log("")
} }
// MARK: - Reschedule calls // MARK: - Reschedule calls
@ -540,8 +545,10 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
for apiCall in apiCallsCopy { for apiCall in apiCallsCopy {
apiCall.attemptsCount += 1 apiCall.attemptsCount += 1
apiCall.lastAttemptDate = Date() apiCall.lastAttemptDate = Date()
do { do {
let _ = try await Store.main.execute(apiCall: apiCall) try await self._executeApiCall(apiCall)
// let _ = try await Store.main.execute(apiCall: apiCall)
} catch { } catch {
Logger.error(error) Logger.error(error)
} }

Loading…
Cancel
Save