From 1d333e6f0346764c1f41e160eaf43debf4e8da2b Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 10 Feb 2025 15:41:30 +0100 Subject: [PATCH] Makes the call creation strategy more resilient --- LeStorage/ApiCallCollection.swift | 29 +++++++++++++---------------- LeStorage/Services.swift | 7 ++++++- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/LeStorage/ApiCallCollection.swift b/LeStorage/ApiCallCollection.swift index c553212..c0f3bd2 100644 --- a/LeStorage/ApiCallCollection.swift +++ b/LeStorage/ApiCallCollection.swift @@ -218,21 +218,19 @@ actor ApiCallCollection: SomeCallCollection { /// The method updates existing calls or creates a new one fileprivate func _callForInstance(_ instance: T, method: HTTPMethod) async throws -> ApiCall? { - if let existingCall = self.items.first(where: { $0.dataId == instance.stringId }) { - switch method { - case .delete: - self.deleteById(existingCall.id) // delete the existing call as we don't need it - if existingCall.method == HTTPMethod.post { - return nil // if the post has not been done, we can just stop here - } else { - return try self._createCall(instance, method: method) // otherwise it's a put and we want to send the delete - } - 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) + // cleanup + let existingCalls = self.items.filter { $0.dataId == instance.stringId } + self._deleteCalls(existingCalls) + + // create + let call = try self._createCall(instance, method: method) + self._prepareCall(apiCall: call) + return call + } + + fileprivate func _deleteCalls(_ calls: [ApiCall]) { + for call in calls { + self.deleteById(call.id) } } @@ -294,7 +292,6 @@ actor ApiCallCollection: SomeCallCollection { /// Initiates the process of sending the data with the server fileprivate func _synchronize(_ instance: T, method: HTTPMethod) async throws -> V? { if let apiCall = try await self._callForInstance(instance, method: method) { - self._prepareCall(apiCall: apiCall) return try await self._executeApiCall(apiCall) } else { return nil diff --git a/LeStorage/Services.swift b/LeStorage/Services.swift index a52e38a..63145c7 100644 --- a/LeStorage/Services.swift +++ b/LeStorage/Services.swift @@ -142,7 +142,7 @@ public class Services { 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) } else { return try jsonDecoder.decode(V.self, from: "{}".data(using: .utf8)!) @@ -280,6 +280,11 @@ public class Services { return try await self._runRequest(postRequest) } + public func delete(_ 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 func runApiCall(_ apiCall: ApiCall) async throws -> V { let request = try self._request(from: apiCall)