I'm using Alamofire's SessionManager to make requests to my API services.
Is there a way to limit the retry counts in Alamofire?
I'm using the new RequestAdapter and RequestTrier Protocols to provide a retry mechanims in Alamofire v4.
I want to limit retries up to 5. If after 5 Retries a new request shouldn't be done.
class VMRetrier: RequestAdapter, RequestRetrier {
public func adapt(_ urlRequest: URLRequest) throws -> URLRequest {
return urlRequest;
}
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion) {
if let response = request.task?.response as? HTTPURLResponse, response.statusCode == 401 {
VMLogger.shared.debug(message: "Trying to get a token")
let _ = AuthService.shared.login(email: "[email protected]", password: "test34")
.then(execute: { (response) in
completion(true, 0.0)
})
}
else {
completion(false, 0.0)
}
} }
Usage:
internal let sessionManager = SessionManager()
override init() {
super.init()
sessionManager.adapter = VMRequestAdapter()
sessionManager.retrier = VMRetrier()
}
UPDATE There is a new commit in alamofire to provide a retry count option.Alamofire Commit
I have solved this with Alamofire's RequestRetrier
protocol:
class Retrier: RequestRetrier {
var defaultRetryCount = 4
private var requestsAndRetryCounts: [(Request, Int)] = []
private var lock = NSLock()
private func index(request: Request) -> Int? {
return requestsAndRetryCounts.index(where: { $0.0 === request })
}
func addRetryInfo(request: Request, retryCount: Int? = nil) {
lock.lock() ; defer { lock.unlock() }
guard index(request: request) == nil else { print("ERROR addRetryInfo called for already tracked request"); return }
requestsAndRetryCounts.append((request, retryCount ?? defaultRetryCount))
}
func deleteRetryInfo(request: Request) {
lock.lock() ; defer { lock.unlock() }
guard let index = index(request: request) else { print("ERROR deleteRetryInfo called for not tracked request"); return }
requestsAndRetryCounts.remove(at: index)
}
func should(_ manager: SessionManager, retry request: Request, with error: Error, completion: @escaping RequestRetryCompletion){
lock.lock() ; defer { lock.unlock() }
guard let index = index(request: request) else { completion(false, 0); return }
let (request, retryCount) = requestsAndRetryCounts[index]
if retryCount == 0 {
completion(false, 0)
} else {
requestsAndRetryCounts[index] = (request, retryCount - 1)
completion(true, 0.5)
}
}
}
Should be used this way:
let manager = SessionManager()
let retrier = Retrier()
// ...
manager.retrier = retrier
then
let request = manager.request(urlString, method: method, parameters: parameters, encoding: JSONEncoding.default, headers: headers)
retrier.addRetryInfo(request: request)
request.response { r in
self.retrier.deleteRetryInfo(request: request)
}.responseApiJSON { (r: DataResponse<JSONObject>) in
// You code here
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With