Makes the call creation strategy more resilient

sync2
Laurent 9 months ago
parent 339df068a8
commit 1d333e6f03
  1. 27
      LeStorage/ApiCallCollection.swift
  2. 7
      LeStorage/Services.swift

@ -218,21 +218,19 @@ actor ApiCallCollection<T: Storable>: SomeCallCollection {
/// The method updates existing calls or creates a new one /// The method updates existing calls or creates a new one
fileprivate func _callForInstance(_ instance: T, method: HTTPMethod) async throws -> ApiCall<T>? { fileprivate func _callForInstance(_ instance: T, method: HTTPMethod) async throws -> ApiCall<T>? {
if let existingCall = self.items.first(where: { $0.dataId == instance.stringId }) { // cleanup
switch method { let existingCalls = self.items.filter { $0.dataId == instance.stringId }
case .delete: self._deleteCalls(existingCalls)
self.deleteById(existingCall.id) // delete the existing call as we don't need it
if existingCall.method == HTTPMethod.post { // create
return nil // if the post has not been done, we can just stop here let call = try self._createCall(instance, method: method)
} else { self._prepareCall(apiCall: call)
return try self._createCall(instance, method: method) // otherwise it's a put and we want to send the delete return call
}
default: // here we should only trying to PUT, so we update the existing POST/PUT with the instance new values
existingCall.body = try instance.jsonString()
return existingCall
} }
} else {
return try self._createCall(instance, method: method) fileprivate func _deleteCalls(_ calls: [ApiCall<T>]) {
for call in calls {
self.deleteById(call.id)
} }
} }
@ -294,7 +292,6 @@ actor ApiCallCollection<T: Storable>: SomeCallCollection {
/// Initiates the process of sending the data with the server /// Initiates the process of sending the data with the server
fileprivate func _synchronize<V: Decodable>(_ instance: T, method: HTTPMethod) async throws -> V? { fileprivate func _synchronize<V: Decodable>(_ instance: T, method: HTTPMethod) async throws -> V? {
if let apiCall = try await self._callForInstance(instance, method: method) { if let apiCall = try await self._callForInstance(instance, method: method) {
self._prepareCall(apiCall: apiCall)
return try await self._executeApiCall(apiCall) return try await self._executeApiCall(apiCall)
} else { } else {
return nil return nil

@ -142,7 +142,7 @@ public class Services {
Logger.w(message) Logger.w(message)
} }
if !(V.self is Empty?.Type) { if !(V.self is Empty?.Type) && !(V.self is Empty.Type) {
return try jsonDecoder.decode(V.self, from: task.0) return try jsonDecoder.decode(V.self, from: task.0)
} else { } else {
return try jsonDecoder.decode(V.self, from: "{}".data(using: .utf8)!) return try jsonDecoder.decode(V.self, from: "{}".data(using: .utf8)!)
@ -280,6 +280,11 @@ public class Services {
return try await self._runRequest(postRequest) return try await self._runRequest(postRequest)
} }
public func delete<T: Storable>(_ instance: T) async throws -> T {
let deleteRequest = try self._deleteRequest(type: T.self, id: instance.stringId)
return try await self._runRequest(deleteRequest)
}
/// Executes an ApiCall /// Executes an ApiCall
func runApiCall<T: Storable, V: Decodable>(_ apiCall: ApiCall<T>) async throws -> V { func runApiCall<T: Storable, V: Decodable>(_ apiCall: ApiCall<T>) async throws -> V {
let request = try self._request(from: apiCall) let request = try self._request(from: apiCall)

Loading…
Cancel
Save