How can I retry failed requests using alamofire?

1.2k Views Asked by At

I append failed requests to queue manager (contains array) in case of no connection

I'm presenting a custom pop-up with a retry button. When the retry button is pressed, I want to retry the requests that cannot be sent in the no connection state. There may be more than one request.

When I try the retryRequest method from Alamofire Session class, the task state of the request remains in the initilazed or finished state, but it must be resumed in order to send the request successfully, how can I solve this situation?

InterceptorInterface.swift

    public func didGetNoInternetConnection() {
    let viewModel = AppPopupViewModel(title: L10n.AppPopUp.areYouOffline, description: L10n.AppPopUp.checkInternetConnection, image: Images.noInternetConnection.image, firstButtonTitle: L10n.General.tryAgain, secondButtonTitle: nil, firstButtonAction: { [weak self] in
        guard let self = self else { return }
        DispatchQueue.main.async {
            self.retry()
        }
    }, secondButtonAction: nil, dismissCompletion: nil, dimColor: Colors.appGray.color.withAlphaComponent(0.8), showCloseButton: true, customView: nil)
    DispatchQueue.main.async {
        AppPopupManager.show(with: viewModel, completion: nil)
    }
}

private func retry() {
    
    guard let head = NetworkRequestStorage.shared.head else {
        return
    }
    let request = head.request
    let session = head.session
    session.retryRequest(request, withDelay: nil)
}

APIInterceptor.swift

final class APIInterceptor: Alamofire.RequestInterceptor {
    private let configure: NetworkConfigurable

    private var lock = NSLock()
    
    // MARK: - Initilize
    internal init(configure: NetworkConfigurable) {
        self.configure = configure
    }

    // MARK: - Request Interceptor Method
    internal func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void) {
        lock.lock()
        defer {
            lock.unlock()
        }
        var urlRequest = urlRequest
        if let token = self.configure.accessToken {
            /// Set the Authorization header value using the access token.
            urlRequest.setValue("Bearer " + token, forHTTPHeaderField: "Authorization")
        }
        // Set Accept-Language header value using language code
        urlRequest.setValue(configure.languageCode, forHTTPHeaderField: "Accept-Language")
        
        // Arrange Request logs for develope and staging environment
        if let reachability = NetworkReachabilityManager(), !reachability.isReachable {
            configure.didGetNoInternetConnection()
            completion(.failure(APIClientError.networkError))
        }
        completion(.success(urlRequest))
    }
    
    
    // MARK: - Error Retry Method
    internal func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
        // Arrange Error logs for develope and staging environment
        
        if let aError = error as? APIClientError, aError.statusCode == 400 { // no connection state
            NetworkRequestStorage.shared.enqueue(request: request, session: session)
            completion(.doNotRetryWithError(error))
        } else {
            request.retryCount <= configure.retryCount ? completion(.retry) : completion(.doNotRetryWithError(error))
        }
    }
}

If the request is successful or there is no connection error, I remove it from the NetworkRequestStoroge class.

0

There are 0 best solutions below