Allow ApiCall execute from external projects

sync2
Laurent 8 months ago
parent 89582de30c
commit 948f1f3444
  1. 19
      LeStorage/ApiCallCollection.swift
  2. 44
      LeStorage/Services.swift
  3. 4
      LeStorage/StoreCenter.swift
  4. 4
      LeStorage/StoredCollection+Sync.swift

@ -194,7 +194,8 @@ actor ApiCallCollection<T: SyncedStorable>: SomeCallCollection {
} else {
let results = try await self._executeApiCalls(batch)
if T.copyServerResponse {
StoreCenter.main.updateLocalInstances(results)
let instances = results.compactMap { $0.data }
StoreCenter.main.updateLocalInstances(instances)
}
}
} catch {
@ -292,7 +293,7 @@ actor ApiCallCollection<T: SyncedStorable>: SomeCallCollection {
}
}
func executeBatch(_ batch: OperationBatch<T>) async throws -> [T] {
func executeBatch(_ batch: OperationBatch<T>) async throws -> [OperationResult<T>] {
var apiCalls: [ApiCall<T>] = []
let transactionId = Store.randomId()
@ -339,8 +340,18 @@ actor ApiCallCollection<T: SyncedStorable>: SomeCallCollection {
/// Executes an API call
/// For POST requests, potentially copies additional data coming from the server during the insert
fileprivate func _executeApiCalls(_ apiCalls: [ApiCall<T>]) async throws -> [T] {
return try await StoreCenter.main.execute(apiCalls: apiCalls)
fileprivate func _executeApiCalls(_ apiCalls: [ApiCall<T>]) async throws -> [OperationResult<T>] {
let results = try await StoreCenter.main.execute(apiCalls: apiCalls)
for result in results {
switch result.status {
case 200..<300:
self.deleteById(result.apiCallId)
default:
break
}
}
return results
}
/// Returns the content of the API call file as a String

@ -297,14 +297,14 @@ public class Services {
/// - request: the URLRequest to run
/// - apiCallId: the id of the ApiCall to delete in case of success, or to schedule for a rerun in case of failure
fileprivate func _runSyncPostRequest<T: SyncedStorable>(
_ request: URLRequest, type: T.Type) async throws -> [T] {
_ request: URLRequest, type: T.Type) async throws -> [OperationResult<T>] {
let debugURL = request.url?.absoluteString ?? ""
// print("Run \(request.httpMethod ?? "") \(debugURL)")
let task: (Data, URLResponse) = try await URLSession.shared.data(for: request)
// print("sync POST \(String(describing: T.self)) => \(String(data: task.0, encoding: .utf8) ?? "")")
// print("sync POST \(String(describing: T.self)) => \(String(data: task.0, encoding: .utf8) ?? "")")
var rescheduleApiCalls: Bool = false
var successes: [T] = []
var results: [OperationResult<T>] = []
if let response = task.1 as? HTTPURLResponse {
let statusCode = response.statusCode
@ -313,20 +313,24 @@ public class Services {
case 200..<300: // success
let decoded: BatchResponse<T> = try self._decode(data: task.0)
results = decoded.results
for result in decoded.results {
switch result.status {
case 200..<300:
if let data = result.data {
successes.append(data)
}
break
// if let data = result.data {
// successes.append(data)
// }
try await StoreCenter.main.deleteApiCallById(type: T.self, id: result.apiCallId)
// try await StoreCenter.main.deleteApiCallById(type: T.self, id: result.apiCallId)
default:
if let message = result.message {
print(message)
}
rescheduleApiCalls = true
break
}
}
@ -357,7 +361,7 @@ public class Services {
try? await StoreCenter.main.rescheduleApiCalls(type: T.self)
}
return successes
return results
}
/// Returns the URLRequest for an ApiCall
@ -547,7 +551,7 @@ public class Services {
}
/// Executes an ApiCall
func runApiCalls<T: SyncedStorable>(_ apiCalls: [ApiCall<T>]) async throws -> [T] {
func runApiCalls<T: SyncedStorable>(_ apiCalls: [ApiCall<T>]) async throws -> [OperationResult<T>] {
let request = try self._syncPostRequest(from: apiCalls)
return try await self._runSyncPostRequest(request, type: T.self)
}
@ -774,21 +778,21 @@ public class Services {
/// Executes a POST request
public func post<T: SyncedStorable>(_ instance: T) async throws -> T? {
let apiCall: ApiCall<T> = ApiCall(method: .post, data: instance)
let results: [T] = try await self.runApiCalls([apiCall])
return results.first
let results: [OperationResult<T>] = try await self.runApiCalls([apiCall])
return results.first?.data
}
/// Executes a PUT request
public func put<T: SyncedStorable>(_ instance: T) async throws -> T {
public func put<T: SyncedStorable>(_ instance: T) async throws -> T? {
let apiCall: ApiCall<T> = ApiCall(method: .put, data: instance)
let results: [T] = try await self.runApiCalls([apiCall])
return results.first!
let results: [OperationResult<T>] = try await self.runApiCalls([apiCall])
return results.first?.data
}
public func delete<T: SyncedStorable>(_ instance: T) async throws -> T {
public func delete<T: SyncedStorable>(_ instance: T) async throws -> T? {
let apiCall: ApiCall<T> = ApiCall(method: .delete, data: instance)
let results: [T] = try await self.runApiCalls([apiCall])
return results.first!
let results: [OperationResult<T>] = try await self.runApiCalls([apiCall])
return results.first?.data
}
/// Returns a POST request for the resource
@ -831,11 +835,11 @@ struct BatchResponse<T: Decodable>: Decodable {
var results: [OperationResult<T>]
}
struct OperationResult<T: Decodable>: Decodable {
public struct OperationResult<T: Decodable>: Decodable {
var apiCallId: String
var status: Int
public var status: Int
var data: T?
var message: String?
public var message: String?
}
struct ErrorMessage {

@ -388,7 +388,7 @@ public class StoreCenter {
}
/// Executes an API call
public func execute<T: SyncedStorable>(apiCalls: [ApiCall<T>]) async throws -> [T] {
public func execute<T: SyncedStorable>(apiCalls: [ApiCall<T>]) async throws -> [OperationResult<T>] {
return try await self.service().runApiCalls(apiCalls)
}
@ -400,7 +400,7 @@ public class StoreCenter {
&& self.userIsAllowed()
}
func sendOperationBatch<T: SyncedStorable>(_ batch: OperationBatch<T>) async throws -> [T] {
func sendOperationBatch<T: SyncedStorable>(_ batch: OperationBatch<T>) async throws -> [OperationResult<T>] {
guard self._canSynchronise() else {
return []
}

@ -216,7 +216,9 @@ extension StoredCollection: SomeSyncedCollection where T : SyncedStorable {
do {
let success = try await StoreCenter.main.sendOperationBatch(batch)
for item in success {
self.updateFromServerInstance(item)
if let data = item.data {
self.updateFromServerInstance(data)
}
}
} catch {
Logger.error(error)

Loading…
Cancel
Save