Skip to content

Commit

Permalink
Allow custom lock tokens (#66)
Browse files Browse the repository at this point in the history
  • Loading branch information
dim committed Apr 27, 2023
1 parent 9de9468 commit 06ee54a
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 32 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## v0.9.3

- Feature: allow custom lock tokens [#66](https://github.com/bsm/redislock/pull/66)

## v0.9.2

- Feature: better handling of nil lock.Release() [#68](https://github.com/bsm/redislock/pull/68)
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/bsm/redislock

go 1.17

require github.com/redis/go-redis/v9 v9.0.2
require github.com/redis/go-redis/v9 v9.0.3

require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
Expand Down
28 changes: 6 additions & 22 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
github.com/bsm/ginkgo/v2 v2.5.0 h1:aOAnND1T40wEdAtkGSkvSICWeQ8L3UASX7YVCqQx+eQ=
github.com/bsm/ginkgo/v2 v2.5.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
github.com/bsm/gomega v1.20.0 h1:JhAwLmtRzXFTx2AkALSLa8ijZafntmhSoU63Ok18Uq8=
github.com/bsm/gomega v1.20.0/go.mod h1:JifAceMQ4crZIWYUKrlGcmbN3bqHogVTADMD2ATsbwk=
github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao=
github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w=
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.0.2 h1:BA426Zqe/7r56kCcvxYLWe1mkaz71LKF77GwgFzSxfE=
github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
github.com/redis/go-redis/v9 v9.0.3 h1:+7mmR26M0IvyLxGZUHxu4GiBkJkVDid0Un+j4ScYu4k=
github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk=
34 changes: 25 additions & 9 deletions redislock.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,14 @@ func New(client RedisClient) *Client {
// Obtain tries to obtain a new lock using a key with the given TTL.
// May return ErrNotObtained if not successful.
func (c *Client) Obtain(ctx context.Context, key string, ttl time.Duration, opt *Options) (*Lock, error) {
token := opt.getToken()

// Create a random token
token, err := c.randomToken()
if err != nil {
return nil, err
if token == "" {
var err error
if token, err = c.randomToken(); err != nil {
return nil, err
}
}

value := token + opt.getMetadata()
Expand All @@ -71,7 +75,7 @@ func (c *Client) Obtain(ctx context.Context, key string, ttl time.Duration, opt
if err != nil {
return nil, err
} else if ok {
return &Lock{Client: c, key: key, value: value}, nil
return &Lock{Client: c, key: key, value: value, tokenLen: len(token)}, nil
}

backoff := retry.NextBackoff()
Expand Down Expand Up @@ -117,8 +121,9 @@ func (c *Client) randomToken() (string, error) {
// Lock represents an obtained, distributed lock.
type Lock struct {
*Client
key string
value string
key string
value string
tokenLen int
}

// Obtain is a short-cut for New(...).Obtain(...).
Expand All @@ -133,12 +138,12 @@ func (l *Lock) Key() string {

// Token returns the token value set by the lock.
func (l *Lock) Token() string {
return l.value[:22]
return l.value[:l.tokenLen]
}

// Metadata returns the metadata of the lock.
func (l *Lock) Metadata() string {
return l.value[22:]
return l.value[l.tokenLen:]
}

// TTL returns the remaining time-to-live. Returns 0 if the lock has expired.
Expand Down Expand Up @@ -197,8 +202,12 @@ type Options struct {
// Default: do not retry
RetryStrategy RetryStrategy

// Metadata string is appended to the lock token.
// Metadata string.
Metadata string

// Token is a unique value that is used to identify the lock. By default, a random tokens are generated. Use this
// option to provide a custom token instead.
Token string
}

func (o *Options) getMetadata() string {
Expand All @@ -208,6 +217,13 @@ func (o *Options) getMetadata() string {
return ""
}

func (o *Options) getToken() string {
if o != nil {
return o.Token
}
return ""
}

func (o *Options) getRetryStrategy() RetryStrategy {
if o != nil && o.RetryStrategy != nil {
return o.RetryStrategy
Expand Down
19 changes: 19 additions & 0 deletions redislock_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,25 @@ func TestObtain_metadata(t *testing.T) {
}
}

func TestObtain_custom_token(t *testing.T) {
ctx := context.Background()
rc := redis.NewClient(redisOpts)
defer teardown(t, rc)

lock, err := Obtain(ctx, rc, lockKey, time.Hour, &Options{Token: "foo", Metadata: "bar"})
if err != nil {
t.Fatal(err)
}
defer lock.Release(ctx)

if exp, got := "foo", lock.Token(); exp != got {
t.Fatalf("expected %v, got %v", exp, got)
}
if exp, got := "bar", lock.Metadata(); exp != got {
t.Fatalf("expected %v, got %v", exp, got)
}
}

func TestObtain_retry_success(t *testing.T) {
ctx := context.Background()
rc := redis.NewClient(redisOpts)
Expand Down

0 comments on commit 06ee54a

Please sign in to comment.