samber / lo

💥 A Lodash-style Go library based on Go 1.18+ Generics (map, filter, contains, find...)
https://pkg.go.dev/github.com/samber/lo
MIT License
17.79k stars 822 forks source link

Add AttemptWithDeadline and AttemptWhileWithDeadline / ETA-based retry strategy #276

Open samber opened 1 year ago

samber commented 1 year ago

This library already provides 4 "retry" helpers:

But a use case is missing: retrying until a deadline is exceeded.

In microservice architectures, we can have service-1, requesting service-2, requesting service-3, requesting service-4... When designing retry strategies, service-4 should retry until service-1 exceeds its intrinsic timeout contract. If the end-to-end timeout is 1s, service-4 must not retry 10 times with a 200ms interval.

I suggest the following prototype: lo.AttemptWithDeadline(maxAttempts, untilDate, func(index int, duration time.Time) error { ... }). If maxAttempts is equal to 0, the callback repeats until untilDate is reached. I'm not sure we need a delay between retries.

WDYT?

nekomeowww commented 1 year ago

Usually, developers may use context.WithTimeout() or context.WithDeadline() when they are involved with deadline stuff, also, for most of the libraries such as gRPC client/server codes that generated from protos, and github.com/go-redis, go.mongodb.org/mongo-driver libraries, they will force the caller to pass context.Context as a parameter in.

So, what about we introduce the variant functions for Attempt* like Attempt*WithContext, but with a additional ctx context.Context parameters required?

I think we could also introduce some utilities functions about context.Context (such as ensuring context.Context as a parameter) to help out the later implementations with context.Context involved? If so, we may build variant functions for Attempt* based on these utilities.