// // API.swift // NotificationService // // Created by Djorkaeff Alexandre Vilela Pereira on 9/16/20. // Copyright © 2020 Rocket.Chat. All rights reserved. // import Foundation struct Retry { let retries: Int let retryTimeout = [10.0, 5.0, 3.0, 1.0] init(retries: Int) { if retries < 0 { self.retries = 0 } else if retries > retryTimeout.count { self.retries = retryTimeout.count } else { self.retries = retries } } var timeout: Double { return retryTimeout[retries - 1] } } final class API { typealias Server = String final let server: URL final let credentials: Credentials? final let decoder = JSONDecoder() static var instances: [Server: API] = [:] convenience init?(server: Server) { guard let server = URL(string: server.removeTrailingSlash()) else { return nil } self.init(server: server) } init(server: URL) { self.server = server self.credentials = Storage.shared.getCredentials(server: server.absoluteString) } func fetch(request: T, retry: Retry? = nil, completion: @escaping((APIResponse) -> Void)) { func onError() { if let retry = retry, retry.retries > 0 { DispatchQueue.main.asyncAfter(deadline: .now() + retry.timeout, execute: { self.fetch(request: request, retry: Retry(retries: retry.retries - 1), completion: completion) }) return } completion(.error) } guard let request = request.request(for: self) else { completion(.error) return } let task = URLSession.shared.dataTask(with: request) {(data, _, error) in if let _ = error as NSError? { onError() return } guard let data = data else { onError() return } if let response = try? self.decoder.decode(T.ResponseType.self, from: data), response.success { completion(.resource(response)) return } onError() } task.resume() } }