Skip to content

Commit

Permalink
Merge branch 'activatedio-master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
hjr265 committed Aug 10, 2020
2 parents 481faa5 + 3359663 commit 3f5ea03
Show file tree
Hide file tree
Showing 18 changed files with 606 additions and 200 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dump.rdb
.idea
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,12 @@ Install Redsync using the go get command:

$ go get github.com/go-redsync/redsync

The only dependencies are the Go distribution and [Redigo](https://github.com/gomodule/redigo).
Two driver implementations will be installed; however, only the one used will be include in your project.

* [Redigo](https://github.com/gomodule/redigo)
* [Go-redis](https://github.com/go-redis/redis)

See the [examples](examples) folder for usage of each driver.

## Documentation

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v1
v2
36 changes: 36 additions & 0 deletions examples/goredis/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package main

import (
goredislib "github.com/go-redis/redis"
"github.com/go-redsync/redsync"
"github.com/go-redsync/redsync/v3/redis"
"github.com/go-redsync/redsync/v3/redis/goredis"
"github.com/stvp/tempredis"
)

func main() {

server, err := tempredis.Start(tempredis.Config{})
if err != nil {
panic(err)
}
defer server.Term()

client := goredislib.NewClient(&goredislib.Options{
Network: "unix",
Addr: server.Socket(),
})

pool := goredis.NewGoredisPool(client)

rs := redsync.New([]redis.Pool{pool})

mutex := rs.NewMutex("test-redsync")
err = mutex.Lock()

if err != nil {
panic(err)
}

mutex.Unlock()
}
43 changes: 43 additions & 0 deletions examples/redigo/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package main

import (
"time"

"github.com/go-redsync/redsync"
"github.com/go-redsync/redsync/v3/redis"
"github.com/go-redsync/redsync/v3/redis/redigo"
redigolib "github.com/gomodule/redigo/redis"
"github.com/stvp/tempredis"
)

func main() {

server, err := tempredis.Start(tempredis.Config{})
if err != nil {
panic(err)
}
defer server.Term()

pool := redigo.NewRedigoPool(&redigolib.Pool{
MaxIdle: 3,
IdleTimeout: 240 * time.Second,
Dial: func() (redigolib.Conn, error) {
return redigolib.Dial("unix", server.Socket())
},
TestOnBorrow: func(c redigolib.Conn, t time.Time) error {
_, err := c.Do("PING")
return err
},
})

rs := redsync.New([]redis.Pool{pool})

mutex := rs.NewMutex("test-redsync")
err = mutex.Lock()

if err != nil {
panic(err)
}

mutex.Unlock()
}
11 changes: 5 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
module github.com/go-redsync/redsync/v2
module github.com/go-redsync/redsync/v3

go 1.13
go 1.14

require (
github.com/go-redis/redis v6.15.9+incompatible
github.com/go-redsync/redsync v1.4.2
github.com/gomodule/redigo v2.0.0+incompatible
github.com/hashicorp/go-multierror v1.1.0
github.com/onsi/ginkgo v1.14.0 // indirect
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203
)

// TODO: Remove this once this issue is addressed, or redigo no longer points to
// v2.0.0+incompatible, above: https://github.com/gomodule/redigo/issues/366
replace github.com/gomodule/redigo => github.com/gomodule/redigo v1.7.0
68 changes: 66 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,72 @@
github.com/gomodule/redigo v1.7.0 h1:ZKld1VOtsGhAe37E7wMxEDgAlGM5dvFY+DiOhSkhP9Y=
github.com/gomodule/redigo v1.7.0/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redsync/redsync v1.4.2 h1:KADEZ2rlaHMZWnlkthQCxfGP+8ZWwJLiSjOYN3mntKA=
github.com/go-redsync/redsync v1.4.2/go.mod h1:my8/M5YL986u2jBMtZTLkBIgBsKNNSixJWzWwISH6Uw=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0 h1:B9UzwGQJehnUY1yNrnwREHc3fGbC2xefo8g4TbElacI=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7 h1:AeiKBIuRw3UomYXSbLy0Mc2dDLfdtbT/IVn4keq83P0=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299 h1:DYfZAGf2WMFjMxbgTjaC+2HC7NkNAQs+6Q8b9WEB/F4=
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
51 changes: 26 additions & 25 deletions mutex.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"encoding/base64"
"time"

"github.com/gomodule/redigo/redis"
"github.com/go-redsync/redsync/v3/redis"
"github.com/hashicorp/go-multierror"
)

Expand All @@ -28,7 +28,7 @@ type Mutex struct {
value string
until time.Time

pools []Pool
pools []redis.Pool
}

// Lock locks m. In case it returns an error on failure, you may retry to acquire the lock by calling this method again.
Expand All @@ -45,7 +45,7 @@ func (m *Mutex) Lock() error {

start := time.Now()

n, err := m.actOnPoolsAsync(func(pool Pool) (bool, error) {
n, err := m.actOnPoolsAsync(func(pool redis.Pool) (bool, error) {
return m.acquire(pool, value)
})
if n == 0 && err != nil {
Expand All @@ -59,7 +59,7 @@ func (m *Mutex) Lock() error {
m.until = until
return nil
}
m.actOnPoolsAsync(func(pool Pool) (bool, error) {
m.actOnPoolsAsync(func(pool redis.Pool) (bool, error) {
return m.release(pool, value)
})
}
Expand All @@ -69,7 +69,7 @@ func (m *Mutex) Lock() error {

// Unlock unlocks m and returns the status of unlock.
func (m *Mutex) Unlock() (bool, error) {
n, err := m.actOnPoolsAsync(func(pool Pool) (bool, error) {
n, err := m.actOnPoolsAsync(func(pool redis.Pool) (bool, error) {
return m.release(pool, m.value)
})
if n < m.quorum {
Expand All @@ -80,7 +80,7 @@ func (m *Mutex) Unlock() (bool, error) {

// Extend resets the mutex's expiry and returns the status of expiry extension.
func (m *Mutex) Extend() (bool, error) {
n, err := m.actOnPoolsAsync(func(pool Pool) (bool, error) {
n, err := m.actOnPoolsAsync(func(pool redis.Pool) (bool, error) {
return m.touch(pool, m.value, int(m.expiry/time.Millisecond))
})
if n < m.quorum {
Expand All @@ -90,16 +90,16 @@ func (m *Mutex) Extend() (bool, error) {
}

func (m *Mutex) Valid() (bool, error) {
n, err := m.actOnPoolsAsync(func(pool Pool) (bool, error) {
n, err := m.actOnPoolsAsync(func(pool redis.Pool) (bool, error) {
return m.valid(pool)
})
return n >= m.quorum, err
}

func (m *Mutex) valid(pool Pool) (bool, error) {
func (m *Mutex) valid(pool redis.Pool) (bool, error) {
conn := pool.Get()
defer conn.Close()
reply, err := redis.String(conn.Do("GET", m.name))
reply, err := conn.Get(m.name)
if err != nil {
return false, err
}
Expand All @@ -115,17 +115,14 @@ func genValue() (string, error) {
return base64.StdEncoding.EncodeToString(b), nil
}

func (m *Mutex) acquire(pool Pool, value string) (bool, error) {
func (m *Mutex) acquire(pool redis.Pool, value string) (bool, error) {
conn := pool.Get()
defer conn.Close()
reply, err := redis.String(conn.Do("SET", m.name, value, "NX", "PX", int(m.expiry/time.Millisecond)))
reply, err := conn.SetNX(m.name, value, m.expiry)
if err != nil {
if err == redis.ErrNil {
return false, nil
}
return false, err
}
return reply == "OK", nil
return reply, nil
}

var deleteScript = redis.NewScript(1, `
Expand All @@ -136,12 +133,14 @@ var deleteScript = redis.NewScript(1, `
end
`)

func (m *Mutex) release(pool Pool, value string) (bool, error) {
func (m *Mutex) release(pool redis.Pool, value string) (bool, error) {
conn := pool.Get()
defer conn.Close()
status, err := redis.Int64(deleteScript.Do(conn, m.name, value))

return err == nil && status != 0, err
status, err := conn.Eval(deleteScript, m.name, value)
if err != nil {
return false, err
}
return status != 0, nil
}

var touchScript = redis.NewScript(1, `
Expand All @@ -152,23 +151,25 @@ var touchScript = redis.NewScript(1, `
end
`)

func (m *Mutex) touch(pool Pool, value string, expiry int) (bool, error) {
func (m *Mutex) touch(pool redis.Pool, value string, expiry int) (bool, error) {
conn := pool.Get()
defer conn.Close()
status, err := redis.Int64(touchScript.Do(conn, m.name, value, expiry))

return err == nil && status != 0, err
status, err := conn.Eval(touchScript, m.name, value, expiry)
if err != nil {
return false, err
}
return status != "ERR", nil
}

func (m *Mutex) actOnPoolsAsync(actFn func(Pool) (bool, error)) (int, error) {
func (m *Mutex) actOnPoolsAsync(actFn func(redis.Pool) (bool, error)) (int, error) {
type result struct {
Status bool
Err error
}

ch := make(chan result)
for _, pool := range m.pools {
go func(pool Pool) {
go func(pool redis.Pool) {
r := result{}
r.Status, r.Err = actFn(pool)
ch <- r
Expand Down
Loading

0 comments on commit 3f5ea03

Please sign in to comment.