92 lines
2.0 KiB
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()
|
|||
}
|
|||
}
|
|||
|