-
Notifications
You must be signed in to change notification settings - Fork 162
Description
Description
Per the example in the official documentation (see: https://pkg.go.dev/github.com/bsm/redislock@v0.9.4#example-Client.Obtain-CustomDeadline), if the Obtain function fails to obtain lock, it will return redislock.ErrNotObtained.
For the following code, lets assume the lock is already obtained and not released.
locker := redislock.New(client)
// Retry every 500ms, for up-to a minute
backoff := redislock.LinearBackoff(500 * time.Millisecond)
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute))
defer cancel()
// Obtain lock with retry + custom deadline
lock, err := locker.Obtain(ctx, "my-key", time.Second, &redislock.Options{
RetryStrategy: backoff,
})
if err == redislock.ErrNotObtained {
fmt.Println("Could not obtain lock!")
} else if err != nil {
log.Fatalln(err)
}Expectation: console will print Could not obtain lock
Observed behaviour: console will print context deadline exceeded and halt function execution (due to log.Fatalln).
Why this occurs
Seems like this change was brought about in #63 and corresponding PR #64
select {
case <-ctx.Done():
return nil, ctx.Err()
case <-ticker.C:
}Suggestion
Replace return nil, ctx.Err() with return nil, errors.Join(ctx.Err(), ErrNotObtained)
This way, if someone does not care why the lock could not be obtained, then they can still check against the ErrNotObtained error.
// assume cannot acquire lock because context deadline is exceeded
lock, err := locker.Obtain(ctx, "key", time.Second, &redislock.Options{RetryStrategy: linearBackoff})
// this condition will be true
if errors.Is(err, redislock.ErrNotObtained) {
fmt.Println("lock not obtained")
}
// this condition will also be true
if errors.Is(err, context.DeadlineExceeded) {
fmt.Println("context deadline exceeded")
}I'd be happy to make an MR to contribute this change if you think this is something valuable. Looking forward to your response, thanks