verdnatura-chat/ios/Shared/RocketChat/API/API.swift

92 lines
2.0 KiB
Swift

//
// 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<T: Request>(request: T, retry: Retry? = nil, completion: @escaping((APIResponse<T.ResponseType>) -> 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()
}
}