-
-
Notifications
You must be signed in to change notification settings - Fork 115
Description
Hi! First of all, I have to say that I really love this library 🙏
The reason for this issue is cause I'm not sure if I found a bug or if I misunderstood the semantics of retry with delay.
Context
I was trying to implement polling to a web server leveraging Promises.
Say we have promise: Promise<Value> which encapsulate the async call to our backend. Then I expressed polling with something like:
promise
.validate { value in /* predicate to decide if continue polling */ }
.retry(10, delay: pollingTime)Expectation
Since:
validaterejects the promise if the predicate is not metretryallow to execute source chained promise if it ends with a rejection (exactly what I need, to re-issue the web call)delayis the delay between each attempt (starting when failed the first time)
My expectation was to retry the promise at most 10 times, each with a delay of pollingTime.
Result
AFAIU, the delay is implemented with the defer which in turn defers only the happy path (then) but the retryWhen is actually targeting a rejected promise. This results in the delay being applied in the only attempt that succeeds (if any).
I've also tried to encapsulate the validate inside the promise (rejecting it if the predicate is not met) but it didn't move the problem.
I could achieve what I expected only pushing the validation inside the promise and implementing a deferAll:
func `deferAll`(in context: Context = .background, _ seconds: TimeInterval) -> Promise<Value> {
guard seconds > 0 else { return self }
let fireTime: DispatchTime = .now() + seconds
return self
.then(in: context) { value in return Promise<Value> { resolve, _, _ in
context.queue.asyncAfter(deadline: fireTime) { resolve(value) }
}}
.recover { error in return Promise<Value> { _, reject, _ in
context.queue.asyncAfter(deadline: fireTime) { reject(error) }
}}
}
}and leveraging it inside the retryWhen in place of the defer.
Am I misunderstanding the semantic of retry with delay?
Thank you 😄