sync2
Laurent 1 year ago
parent aa78348e98
commit 214420f98a
  1. 20
      LeStorage/ApiCallCollection.swift
  2. 2
      LeStorage/Services.swift
  3. 5
      LeStorage/StoredCollection.swift

@ -19,6 +19,10 @@ protocol SomeCallCollection {
}
enum ApiCallError: Error {
case cantCreateCall
}
/// ApiCallCollection is an object communicating with a server to synchronize data managed locally
/// The Api calls are serialized and stored in a JSON file
/// Failing Api calls are stored forever and will be executed again later
@ -227,12 +231,17 @@ actor ApiCallCollection<T: Storable>: SomeCallCollection {
/// Creates an API call for the Storable [instance] and an HTTP [method]
fileprivate func _createCall(_ instance: T, method: HTTPMethod) throws -> ApiCall<T> {
let jsonString = try instance.jsonString()
return ApiCall(method: method, dataId: instance.stringId, body: jsonString)
do {
let jsonString = try instance.jsonString()
return ApiCall(method: method, dataId: instance.stringId, body: jsonString)
} catch {
StoreCenter.main.log(message: "call could not be created for \(T.resourceName()): \(error.localizedDescription)")
throw ApiCallError.cantCreateCall
}
}
/// Prepares a call for execution by updating its properties and adding it to its collection for storage
fileprivate func _prepareCall(apiCall: ApiCall<T>) throws {
fileprivate func _prepareCall(apiCall: ApiCall<T>) {
apiCall.lastAttemptDate = Date()
apiCall.attemptsCount += 1
self.addOrUpdate(apiCall)
@ -244,6 +253,7 @@ actor ApiCallCollection<T: Storable>: SomeCallCollection {
return try await self._synchronize(instance, method: HTTPMethod.post)
} catch {
self.rescheduleApiCallsIfNecessary()
StoreCenter.main.log(message: "POST failed for \(instance)")
Logger.error(error)
}
return nil
@ -256,6 +266,7 @@ actor ApiCallCollection<T: Storable>: SomeCallCollection {
return try await self._synchronize(instance, method: HTTPMethod.put)
} catch {
self.rescheduleApiCallsIfNecessary()
StoreCenter.main.log(message: "PUT failed for \(instance)")
Logger.error(error)
}
return nil
@ -267,6 +278,7 @@ actor ApiCallCollection<T: Storable>: SomeCallCollection {
let _: Empty? = try await self._synchronize(instance, method: HTTPMethod.delete)
} catch {
self.rescheduleApiCallsIfNecessary()
StoreCenter.main.log(message: "DELETE failed for \(instance)")
Logger.error(error)
}
return
@ -275,7 +287,7 @@ actor ApiCallCollection<T: Storable>: SomeCallCollection {
/// Initiates the process of sending the data with the server
fileprivate func _synchronize<V: Decodable>(_ instance: T, method: HTTPMethod) async throws -> V? {
if let apiCall = try self._callForInstance(instance, method: method) {
try self._prepareCall(apiCall: apiCall)
self._prepareCall(apiCall: apiCall)
return try await self._executeApiCall(apiCall)
} else {
return nil

@ -121,7 +121,7 @@ public class Services {
print("\(debugURL) ended, status code = \(statusCode)")
switch statusCode {
case 200..<300: // success
try await StoreCenter.main.deleteApiCallById(type: T.self, id: apiCall.id)
try await StoreCenter.main.deleteApiCallById(type: T.self, id: apiCall.id)
default: // error
Logger.log("Failed Run \(request.httpMethod ?? "") \(request.url?.absoluteString ?? "")")
let errorString: String = String(data: task.0, encoding: .utf8) ?? ""

@ -399,14 +399,13 @@ 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 to \(T.fileName())...")
do {
let jsonString: String = try self.items.jsonString()
try self._store.write(content: jsonString, fileName: T.fileName())
} catch {
Logger.error(error) // TODO how to notify the main project
Logger.error(error)
StoreCenter.main.log(message: "write failed for \(T.resourceName()): \(error.localizedDescription)")
}
// Logger.log("End write")
}
/// Simply clears the items of the collection

Loading…
Cancel
Save