Peter Lapisu
Peter Lapisu

Reputation: 20975

Alamofire RequestRetrier, is it ok to call the completion block on the main operation queue?

I have been wondering if calling the completion block from the request retry on the main queue, is ok, since the function call is made on the session.rootQueue

func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void) {
    
        OperationQueue.main.addOperation { [weak self] in
            
            guard let self = self else {
                completion(.doNotRetryWithError(e))
                return
            }
            self.handleError(e, completion: completion)
            
        }
        
    }
    
}

the docu doesn't explicitly state that, but if i am not mistaken, it is generally expected to call completion blocks on the same queue as the function call was made

public protocol RequestRetrier {
    /// Determines whether the `Request` should be retried by calling the `completion` closure.
    ///
    /// This operation is fully asynchronous. Any amount of time can be taken to determine whether the request needs
    /// to be retried. The one requirement is that the completion closure is called to ensure the request is properly
    /// cleaned up after.
    ///
    /// - Parameters:
    ///   - request:    `Request` that failed due to the provided `Error`.
    ///   - session:    `Session` that produced the `Request`.
    ///   - error:      `Error` encountered while executing the `Request`.
    ///   - completion: Completion closure to be executed when a retry decision has been determined.
    func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void)

so my question is, on which queue should the completion be called?

Upvotes: 0

Views: 393

Answers (1)

Jon Shier
Jon Shier

Reputation: 12770

Yes, it's safe, as the internal implementation that calls your retrier immediately calls back onto Alamofire's rootQueue.

As of Alamofire 5.4.4:

retrier.retry(request, for: self, dueTo: error) { retryResult in
    self.rootQueue.async {
        guard let retryResultError = retryResult.error else { completion(retryResult); return }

        let retryError = AFError.requestRetryFailed(retryError: retryResultError, originalError:
error)
        completion(.doNotRetryWithError(retryError))
    }
}

Upvotes: 1

Related Questions