Fixes for failed api calls

multistore
Laurent 1 year ago
parent eaada945fb
commit 9fde5ac8b3
  1. 10
      LeStorage/Codables/FailedAPICall.swift
  2. 26
      LeStorage/Services.swift
  3. 6
      LeStorage/Store.swift

@ -9,14 +9,17 @@ import Foundation
class FailedAPICall: ModelObject, Storable {
static func resourceName() -> String { return "failed_api_calls" }
static func tokenExemptedMethods() -> [HTTPMethod] { return HTTPMethod.allCases }
static func resourceName() -> String { return "failed-api-calls" }
static func tokenExemptedMethods() -> [HTTPMethod] { return [] }
var id: String = Store.randomId()
/// The creation date of the call
var date: Date = Date()
/// The user having the issue
var user: String
/// The id of the API call
var callId: String
@ -29,7 +32,8 @@ class FailedAPICall: ModelObject, Storable {
/// The server error
var error: String
init(callId: String, type: String, apiCall: String, error: String) {
init(user: String, callId: String, type: String, apiCall: String, error: String) {
self.user = user
self.callId = callId
self.type = type
self.apiCall = apiCall

@ -89,7 +89,7 @@ public class Services {
fileprivate func _runRequest<T: Decodable>(_ request: URLRequest, apiCallId: String? = nil) async throws -> T {
Logger.log("Run \(request.httpMethod ?? "") \(request.url?.absoluteString ?? "")")
let task: (Data, URLResponse) = try await URLSession.shared.data(for: request)
Logger.log("response = \(String(describing: String(data: task.0, encoding: .utf8)))")
Logger.log("response = \(String(data: task.0, encoding: .utf8) ?? "")")
if let response = task.1 as? HTTPURLResponse {
let statusCode = response.statusCode
@ -104,12 +104,11 @@ public class Services {
}
default:
Logger.log("Failed Run \(request.httpMethod ?? "") \(request.url?.absoluteString ?? "")")
var errorString = String(describing: String(data: task.0, encoding: .utf8))
if let nfe: NonFieldError = try? JSONDecoder().decode(NonFieldError.self, from: task.0) {
if let reason = nfe.non_field_errors.first {
errorString = reason
}
var errorString: String = String(data: task.0, encoding: .utf8) ?? ""
if let message = self.errorMessageFromResponse(data: task.0) {
errorString = message
}
if let apiCallId, let type = (T.self as? any Storable.Type) {
try Store.main.rescheduleApiCall(id: apiCallId, type: type)
@ -287,6 +286,18 @@ public class Services {
try self.keychainStore.deleteToken()
}
fileprivate func errorMessageFromResponse(data: Data) -> String? {
do {
if let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any], let stringsArray = jsonObject.values.first as? [String] {
return stringsArray.first
}
} catch {
print("Failed to parse JSON: \(error.localizedDescription)")
}
return nil
}
}
struct AuthResponse: Codable {
@ -303,9 +314,6 @@ struct Token: Codable {
struct Email: Codable {
var email: String
}
struct NonFieldError: Codable {
var non_field_errors: [String]
}
public protocol UserBase: Codable {
var id: String { get }

@ -271,15 +271,15 @@ public class Store {
func logFailedAPICall(_ apiCallId: String, collectionName: String, error: String) {
guard let failedAPICallsCollection = self._failedAPICallsCollection, let collection = self._collections[collectionName], let apiCall = try? collection.apiCallById(apiCallId) else {
guard let failedAPICallsCollection = self._failedAPICallsCollection, let collection = self._collections[collectionName], let apiCall = try? collection.apiCallById(apiCallId), let userId = Store.main.userId else {
return
}
if !failedAPICallsCollection.contains(where: { $0.callId == apiCallId }) && apiCall.attemptsCount > 5 {
do {
let string = try apiCall.jsonString()
let failedAPICall = FailedAPICall(callId: apiCall.id, type: collectionName, apiCall: string, error: error)
let failedAPICall = FailedAPICall(user: userId, callId: apiCall.id, type: collectionName, apiCall: string, error: error)
try failedAPICallsCollection.addOrUpdate(instance: failedAPICall)
} catch {
Logger.error(error)

Loading…
Cancel
Save