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 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
static func tokenExemptedMethods() -> [HTTPMethod]
/// A method that deletes the local dependencies of the resource
/// Mimics the behavior the cascading delete on the django server
/// 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
func deleteDependencies() throws
func copyFromServerInstance(_ instance: any Storable) -> Bool
}
extension Storable {

@ -195,7 +195,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
do {
let items: [T] = try await self._store.getItems()
try self._addOrUpdate(contentOfs: items, shouldSync: false)
self._hasChanged = true
// self._hasChanged = true
self.hasLoadedFromServer = true
NotificationCenter.default.post(name: NSNotification.Name.CollectionDidLoad, object: self)
} catch {
@ -360,7 +360,7 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
/// Writes all the items as a json array inside a file
fileprivate func _write() {
Logger.log("Start write...")
Logger.log("Start write to \(T.fileName())...")
do {
let jsonString: String = try self.items.jsonString()
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]
fileprivate func _createCall(_ instance: T, method: HTTPMethod) throws -> ApiCall<T> {
// let baseURL = try _store.service().baseURL
let jsonString = try instance.jsonString()
return ApiCall(method: method, dataId: String(instance.id), body: jsonString)
}
@ -446,20 +445,14 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
return
}
if let apiCall = try self._callForInstance(instance, method: HTTPMethod.post) {
try self._prepareCall(apiCall: apiCall)
Task {
do {
_ = try await self._store.execute(apiCall: apiCall)
} catch {
self.rescheduleApiCallsIfNecessary()
Logger.error(error)
}
Task {
do {
try await self._synchronize(instance, method: HTTPMethod.post)
} catch {
self.rescheduleApiCallsIfNecessary()
Logger.error(error)
}
}
}
/// 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 {
return
}
if let apiCall = try self._callForInstance(instance, method: HTTPMethod.put) {
try self._prepareCall(apiCall: apiCall)
Task {
do {
_ = try await self._store.execute(apiCall: apiCall)
} catch {
Logger.error(error)
self.rescheduleApiCallsIfNecessary()
}
Task {
do {
try await self._synchronize(instance, method: HTTPMethod.put)
} catch {
self.rescheduleApiCallsIfNecessary()
Logger.error(error)
}
}
}
/// 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 {
return
}
if let apiCall = try self._callForInstance(instance, method: HTTPMethod.delete) {
Task {
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)
Task {
do {
_ = try await self._store.execute(apiCall: apiCall)
} catch {
Logger.error(error)
self.rescheduleApiCallsIfNecessary()
try await self._executeApiCall(apiCall)
}
}
fileprivate func _executeApiCall(_ apiCall: ApiCall<T>) async throws {
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
@ -540,8 +545,10 @@ public class StoredCollection<T: Storable>: RandomAccessCollection, SomeCollecti
for apiCall in apiCallsCopy {
apiCall.attemptsCount += 1
apiCall.lastAttemptDate = Date()
do {
let _ = try await Store.main.execute(apiCall: apiCall)
try await self._executeApiCall(apiCall)
// let _ = try await Store.main.execute(apiCall: apiCall)
} catch {
Logger.error(error)
}

Loading…
Cancel
Save