32 lines
971 B
Swift
32 lines
971 B
Swift
import Foundation
|
|
|
|
enum ProviderCandidateRetryRunnerError: Error {
|
|
case noCandidates
|
|
}
|
|
|
|
enum ProviderCandidateRetryRunner {
|
|
static func run<Candidate, Output>(
|
|
_ candidates: [Candidate],
|
|
shouldRetry: (Error) -> Bool,
|
|
onRetry: (Candidate, Error) -> Void = { _, _ in },
|
|
attempt: (Candidate) async throws -> Output) async throws -> Output
|
|
{
|
|
guard !candidates.isEmpty else {
|
|
throw ProviderCandidateRetryRunnerError.noCandidates
|
|
}
|
|
|
|
for (index, candidate) in candidates.enumerated() {
|
|
do {
|
|
return try await attempt(candidate)
|
|
} catch {
|
|
let hasMoreCandidates = index + 1 < candidates.count
|
|
guard hasMoreCandidates, shouldRetry(error) else {
|
|
throw error
|
|
}
|
|
onRetry(candidate, error)
|
|
}
|
|
}
|
|
throw ProviderCandidateRetryRunnerError.noCandidates
|
|
}
|
|
}
|