1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2025-05-17 22:22:45 +02:00
Muhammad Arham 1e21a56f99
Update go-redis/redis to v9. (#1847)
* Update go-redis/redis to v9.
- And updated redislock, testify, ginko and gomega have also been updated.
- Renamed the option `IdleTimeout` to `ConnMaxIdleTime` because of 517938a6b0/CHANGELOG.md

* Update CHANGELOG.md

* Dropping dot import of the types since they created aliases now

* fixing some error messages to make tests happy

* updating more error messages that were changed to make tests happy

* reverting error messages

Co-authored-by: Muhammad Arham <marham@i2cinc.com>
2022-10-24 16:41:06 +01:00

85 lines
1.9 KiB
Go

package redis
import (
"context"
"errors"
"fmt"
"time"
"github.com/bsm/redislock"
"github.com/go-redis/redis/v9"
"github.com/oauth2-proxy/oauth2-proxy/v7/pkg/apis/sessions"
)
const LockSuffix = "lock"
type Lock struct {
client redis.Cmdable
locker *redislock.Client
lock *redislock.Lock
key string
}
// NewLock instantiate a new lock instance. This will not yet apply a lock on Redis side.
// For that you have to call Obtain(ctx context.Context, expiration time.Duration)
func NewLock(client redis.Cmdable, key string) sessions.Lock {
return &Lock{
client: client,
locker: redislock.New(client),
key: key,
}
}
// Obtain obtains a distributed lock on Redis for the configured key.
func (l *Lock) Obtain(ctx context.Context, expiration time.Duration) error {
lock, err := l.locker.Obtain(ctx, l.lockKey(), expiration, nil)
if errors.Is(err, redislock.ErrNotObtained) {
return sessions.ErrLockNotObtained
}
if err != nil {
return err
}
l.lock = lock
return nil
}
// Refresh refreshes an already existing lock.
func (l *Lock) Refresh(ctx context.Context, expiration time.Duration) error {
if l.lock == nil {
return sessions.ErrNotLocked
}
err := l.lock.Refresh(ctx, expiration, nil)
if errors.Is(err, redislock.ErrNotObtained) {
return sessions.ErrNotLocked
}
return err
}
// Peek returns true, if the lock is still applied.
func (l *Lock) Peek(ctx context.Context) (bool, error) {
v, err := l.client.Exists(ctx, l.lockKey()).Result()
if err != nil {
return false, err
}
if v == 0 {
return false, nil
}
return true, nil
}
// Release releases the lock on Redis side.
func (l *Lock) Release(ctx context.Context) error {
if l.lock == nil {
return sessions.ErrNotLocked
}
err := l.lock.Release(ctx)
if errors.Is(err, redislock.ErrLockNotHeld) {
return sessions.ErrNotLocked
}
return err
}
func (l *Lock) lockKey() string {
return fmt.Sprintf("%s.%s", l.key, LockSuffix)
}