|
|
|
|
@ -76,71 +76,6 @@ public class Services { |
|
|
|
|
return try await _runRequest(request) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Runs a request using a traditional URLRequest |
|
|
|
|
/// - Parameters: |
|
|
|
|
/// - 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] { |
|
|
|
|
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) ?? "")") |
|
|
|
|
|
|
|
|
|
var rescheduleApiCalls: Bool = false |
|
|
|
|
var success: [T] = [] |
|
|
|
|
|
|
|
|
|
if let response = task.1 as? HTTPURLResponse { |
|
|
|
|
let statusCode = response.statusCode |
|
|
|
|
print("\(debugURL) ended, status code = \(statusCode)") |
|
|
|
|
switch statusCode { |
|
|
|
|
case 200..<300: // success |
|
|
|
|
|
|
|
|
|
let decoded: BatchResponse<T> = try self._decode(data: task.0) |
|
|
|
|
for result in decoded.results { |
|
|
|
|
|
|
|
|
|
switch result.status { |
|
|
|
|
case 200..<300: |
|
|
|
|
if let data = result.data { |
|
|
|
|
success.append(data) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try await StoreCenter.main.deleteApiCallById(type: T.self, id: result.apiCallId) |
|
|
|
|
default: |
|
|
|
|
rescheduleApiCalls = true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
default: // error |
|
|
|
|
Logger.log( |
|
|
|
|
"Failed Run \(request.httpMethod ?? "") \(request.url?.absoluteString ?? "")") |
|
|
|
|
let errorString: String = String(data: task.0, encoding: .utf8) ?? "" |
|
|
|
|
var errorMessage = ErrorMessage(error: errorString, domain: "") |
|
|
|
|
|
|
|
|
|
if let message = self.errorMessageFromResponse(data: task.0) { |
|
|
|
|
errorMessage = message |
|
|
|
|
} |
|
|
|
|
try await StoreCenter.main.rescheduleApiCalls(type: T.self) |
|
|
|
|
|
|
|
|
|
// StoreCenter.main.logFailedAPICall( |
|
|
|
|
// apiCall.id, request: request, collectionName: T.resourceName(), |
|
|
|
|
// error: errorMessage.message) |
|
|
|
|
|
|
|
|
|
throw ServiceError.responseError(response: errorMessage.error) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
let message: String = "Unexpected and unmanaged URL Response \(task.1)" |
|
|
|
|
StoreCenter.main.log(message: message) |
|
|
|
|
Logger.w(message) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if rescheduleApiCalls { |
|
|
|
|
try? await StoreCenter.main.rescheduleApiCalls(type: T.self) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return success |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Runs a request using a traditional URLRequest |
|
|
|
|
/// - Parameters: |
|
|
|
|
/// - request: the URLRequest to run |
|
|
|
|
@ -324,6 +259,71 @@ public class Services { |
|
|
|
|
return request |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Runs a request using a traditional URLRequest |
|
|
|
|
/// - Parameters: |
|
|
|
|
/// - 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] { |
|
|
|
|
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) ?? "")") |
|
|
|
|
|
|
|
|
|
var rescheduleApiCalls: Bool = false |
|
|
|
|
var success: [T] = [] |
|
|
|
|
|
|
|
|
|
if let response = task.1 as? HTTPURLResponse { |
|
|
|
|
let statusCode = response.statusCode |
|
|
|
|
print("\(debugURL) ended, status code = \(statusCode)") |
|
|
|
|
switch statusCode { |
|
|
|
|
case 200..<300: // success |
|
|
|
|
|
|
|
|
|
let decoded: BatchResponse<T> = try self._decode(data: task.0) |
|
|
|
|
for result in decoded.results { |
|
|
|
|
|
|
|
|
|
switch result.status { |
|
|
|
|
case 200..<300: |
|
|
|
|
if let data = result.data { |
|
|
|
|
success.append(data) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
try await StoreCenter.main.deleteApiCallById(type: T.self, id: result.apiCallId) |
|
|
|
|
default: |
|
|
|
|
rescheduleApiCalls = true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
default: // error |
|
|
|
|
Logger.log( |
|
|
|
|
"Failed Run \(request.httpMethod ?? "") \(request.url?.absoluteString ?? "")") |
|
|
|
|
let errorString: String = String(data: task.0, encoding: .utf8) ?? "" |
|
|
|
|
var errorMessage = ErrorMessage(error: errorString, domain: "") |
|
|
|
|
|
|
|
|
|
if let message = self.errorMessageFromResponse(data: task.0) { |
|
|
|
|
errorMessage = message |
|
|
|
|
} |
|
|
|
|
try await StoreCenter.main.rescheduleApiCalls(type: T.self) |
|
|
|
|
|
|
|
|
|
// StoreCenter.main.logFailedAPICall( |
|
|
|
|
// apiCall.id, request: request, collectionName: T.resourceName(), |
|
|
|
|
// error: errorMessage.message) |
|
|
|
|
|
|
|
|
|
throw ServiceError.responseError(response: errorMessage.error) |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
let message: String = "Unexpected and unmanaged URL Response \(task.1)" |
|
|
|
|
StoreCenter.main.log(message: message) |
|
|
|
|
Logger.w(message) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if rescheduleApiCalls { |
|
|
|
|
try? await StoreCenter.main.rescheduleApiCalls(type: T.self) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return success |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Returns the URLRequest for an ApiCall |
|
|
|
|
/// - Parameters: |
|
|
|
|
/// - apiCall: An ApiCall instance to configure the returned request |
|
|
|
|
|