From 5fb3dbe7f56c23d55ef852772de5348ff260cc32 Mon Sep 17 00:00:00 2001 From: Ben Tomasini Date: Fri, 14 Dec 2018 10:37:27 -0800 Subject: [PATCH 1/5] Redigo tests are working. Still need to make the goredis tests function --- .gitignore | 2 + go.mod | 3 + go.sum | 29 +++++++ mutex.go | 22 +++-- mutex_test.go | 167 +++++++++++++++++------------------- redis.go | 8 -- redis/goredis/goredis.go | 73 ++++++++++++++++ redis/redigo/redigo.go | 72 ++++++++++++++++ redis/redigo/redigo_test.go | 7 ++ redis/redis.go | 49 +++++++++++ redis/redis_test.go | 1 + redsync.go | 9 +- redsync_test.go | 84 ++++++++++++++++-- 13 files changed, 410 insertions(+), 116 deletions(-) create mode 100644 .gitignore delete mode 100644 redis.go create mode 100644 redis/goredis/goredis.go create mode 100644 redis/redigo/redigo.go create mode 100644 redis/redigo/redigo_test.go create mode 100644 redis/redis.go create mode 100644 redis/redis_test.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..adcfd6c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +dump.rdb +.idea diff --git a/go.mod b/go.mod index 97d61c0..ac42908 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,9 @@ module github.com/go-redsync/redsync require ( + github.com/go-redis/redis v6.14.2+incompatible github.com/gomodule/redigo v2.0.0+incompatible + github.com/onsi/ginkgo v1.7.0 // indirect + github.com/onsi/gomega v1.4.3 // indirect github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 ) diff --git a/go.sum b/go.sum index 0199cb5..0c35419 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,33 @@ +github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-redis/redis v6.14.2+incompatible h1:UE9pLhzmWf+xHNmZsoccjXosPicuiNaInPgym8nzfg0= +github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 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/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= 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/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6ZhfOqbKu7X5eyFl8ZhKvA= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e h1:o3PsSEY8E4eXWkXrIP9YJALUkVZqzHJT5DOasTyn8Vs= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +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 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +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.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/mutex.go b/mutex.go index c081791..cc2cbd1 100644 --- a/mutex.go +++ b/mutex.go @@ -6,7 +6,7 @@ import ( "sync" "time" - "github.com/gomodule/redigo/redis" + "github.com/go-redsync/redsync/redis" ) // A DelayFunc is used to decide the amount of time to wait between retries. @@ -29,7 +29,7 @@ type Mutex struct { nodem sync.Mutex - 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. @@ -110,11 +110,15 @@ func (m *Mutex) genValue() (string, error) { return base64.StdEncoding.EncodeToString(b), nil } -func (m *Mutex) acquire(pool Pool, value string) bool { +func (m *Mutex) acquire(pool redis.Pool, value string) bool { conn := pool.Get() defer conn.Close() - reply, err := redis.String(conn.Do("SET", m.name, value, "NX", "PX", int(m.expiry/time.Millisecond))) - return err == nil && reply == "OK" + reply, err := conn.SetNX(m.name, value, m.expiry) + if err != nil { + return false + } else { + return reply + } } var deleteScript = redis.NewScript(1, ` @@ -125,10 +129,10 @@ var deleteScript = redis.NewScript(1, ` end `) -func (m *Mutex) release(pool Pool, value string) bool { +func (m *Mutex) release(pool redis.Pool, value string) bool { conn := pool.Get() defer conn.Close() - status, err := deleteScript.Do(conn, m.name, value) + status, err := conn.Eval(deleteScript, m.name, value) return err == nil && status != 0 } @@ -140,9 +144,9 @@ var touchScript = redis.NewScript(1, ` end `) -func (m *Mutex) touch(pool Pool, value string, expiry int) bool { +func (m *Mutex) touch(pool redis.Pool, value string, expiry int) bool { conn := pool.Get() defer conn.Close() - status, err := redis.String(touchScript.Do(conn, m.name, value, expiry)) + status, err := conn.Eval(touchScript, m.name, value, expiry) return err == nil && status != "ERR" } diff --git a/mutex_test.go b/mutex_test.go index 3a11ecf..ed4a6b8 100644 --- a/mutex_test.go +++ b/mutex_test.go @@ -5,113 +5,100 @@ import ( "testing" "time" - "github.com/gomodule/redigo/redis" - "github.com/stvp/tempredis" + redsyncredis "github.com/go-redsync/redsync/redis" ) func TestMutex(t *testing.T) { - pools := newMockPools(8) - mutexes := newTestMutexes(pools, "test-mutex", 8) - orderCh := make(chan int) - for i, mutex := range mutexes { - go func(i int, mutex *Mutex) { - err := mutex.Lock() - if err != nil { - t.Fatalf("Expected err == nil, got %q", err) + for k, v := range makeCases(8) { + t.Run(k, func(t *testing.T) { + mutexes := newTestMutexes(v.pool, "test-mutex", v.poolCount) + orderCh := make(chan int) + for i, mutex := range mutexes { + go func(i int, mutex *Mutex) { + err := mutex.Lock() + if err != nil { + t.Fatalf("Expected err == nil, got %q", err) + } + defer mutex.Unlock() + + assertAcquired(t, v.pool, mutex) + + orderCh <- i + }(i, mutex) + } + for range mutexes { + <-orderCh } - defer mutex.Unlock() - - assertAcquired(t, pools, mutex) - orderCh <- i - }(i, mutex) - } - for range mutexes { - <-orderCh + }) } } func TestMutexExtend(t *testing.T) { - pools := newMockPools(8) - mutexes := newTestMutexes(pools, "test-mutex-extend", 1) - mutex := mutexes[0] - - err := mutex.Lock() - if err != nil { - t.Fatalf("Expected err == nil, got %q", err) - } - defer mutex.Unlock() - - time.Sleep(1 * time.Second) + for k, v := range makeCases(8) { + t.Run(k, func(t *testing.T) { + mutexes := newTestMutexes(v.pool, "test-mutex-extend", 1) + mutex := mutexes[0] - expiries := getPoolExpiries(pools, mutex.name) - ok := mutex.Extend() - if !ok { - t.Fatalf("Expected ok == true, got %v", ok) - } - expiries2 := getPoolExpiries(pools, mutex.name) - - for i, expiry := range expiries { - if expiry >= expiries2[i] { - t.Fatalf("Expected expiries[%d] > expiry, got %d %d", i, expiries2[i], expiry) - } - } -} - -func TestMutexQuorum(t *testing.T) { - pools := newMockPools(4) - for mask := 0; mask < 1<= len(pools)/2+1 { err := mutex.Lock() if err != nil { t.Fatalf("Expected err == nil, got %q", err) } - assertAcquired(t, pools, mutex) - } else { - err := mutex.Lock() - if err != ErrFailed { - t.Fatalf("Expected err == %q, got %q", ErrFailed, err) + defer mutex.Unlock() + + time.Sleep(1 * time.Second) + + expiries := getPoolExpiries(v.pool, mutex.name) + ok := mutex.Extend() + if !ok { + t.Fatalf("Expected ok == true, got %v", ok) } - } + expiries2 := getPoolExpiries(v.pool, mutex.name) + + for i, expiry := range expiries { + if expiry >= expiries2[i] { + t.Fatalf("Expected expiries[%d] > expiry, got %d %d", i, expiries2[i], expiry) + } + } + + }) } } -func newMockPools(n int) []Pool { - pools := []Pool{} - for _, server := range servers { - func(server *tempredis.Server) { - pools = append(pools, &redis.Pool{ - MaxIdle: 3, - IdleTimeout: 240 * time.Second, - Dial: func() (redis.Conn, error) { - return redis.Dial("unix", server.Socket()) - }, - TestOnBorrow: func(c redis.Conn, t time.Time) error { - _, err := c.Do("PING") - return err - }, - }) - }(server) - if len(pools) == n { - break - } +func TestMutexQuorum(t *testing.T) { + for k, v := range makeCases(4) { + t.Run(k, func(t *testing.T) { + for mask := 0; mask < 1<= len(v.pool)/2+1 { + err := mutex.Lock() + if err != nil { + t.Fatalf("Expected err == nil, got %q", err) + } + assertAcquired(t, v.pool, mutex) + } else { + err := mutex.Lock() + if err != ErrFailed { + t.Fatalf("Expected err == %q, got %q", ErrFailed, err) + } + } + } + }) } - return pools } -func getPoolValues(pools []Pool, name string) []string { +func getPoolValues(pools []redsyncredis.Pool, name string) []string { values := []string{} for _, pool := range pools { conn := pool.Get() - value, err := redis.String(conn.Do("GET", name)) + value, err := conn.Get(name) conn.Close() - if err != nil && err != redis.ErrNil { + if err != nil { panic(err) } values = append(values, value) @@ -119,21 +106,21 @@ func getPoolValues(pools []Pool, name string) []string { return values } -func getPoolExpiries(pools []Pool, name string) []int { +func getPoolExpiries(pools []redsyncredis.Pool, name string) []int { expiries := []int{} for _, pool := range pools { conn := pool.Get() - expiry, err := redis.Int(conn.Do("PTTL", name)) + expiry, err := conn.PTTL(name) conn.Close() - if err != nil && err != redis.ErrNil { + if err != nil { panic(err) } - expiries = append(expiries, expiry) + expiries = append(expiries, int(expiry)) } return expiries } -func clogPools(pools []Pool, mask int, mutex *Mutex) int { +func clogPools(pools []redsyncredis.Pool, mask int, mutex *Mutex) int { n := 0 for i, pool := range pools { if mask&(1< 0 { + + keys = []string{} + + for i := 0; i < script.KeyCount; i++ { + keys = append(keys, keysAndArgs[i].(string)) + } + + args = keysAndArgs[script.KeyCount:] + + } else { + keys = []string{} + args = keysAndArgs + } + + v, err := self.delegate.EvalSha(script.Hash, keys, args...).Result() + if err != nil && strings.HasPrefix(err.Error(), "NOSCRIPT ") { + v, err = self.delegate.Eval(script.Src, keys, args...).Result() + } + return v, err +} + +func (self *GoredisConn) Close() error { + // Not needed for this library + return nil +} diff --git a/redis/redigo/redigo.go b/redis/redigo/redigo.go new file mode 100644 index 0000000..599f125 --- /dev/null +++ b/redis/redigo/redigo.go @@ -0,0 +1,72 @@ +package redigo + +import ( + redsyncredis "github.com/go-redsync/redsync/redis" + "github.com/gomodule/redigo/redis" + "strings" + "time" +) + +type RedigoPool struct { + delegate *redis.Pool +} + +func (self *RedigoPool) Get() redsyncredis.Conn { + return &RedigoConn{self.delegate.Get()} +} + +func NewRedigoPool(delegate *redis.Pool) *RedigoPool { + return &RedigoPool{delegate} +} + +type RedigoConn struct { + delegate redis.Conn +} + +func (self *RedigoConn) Get(name string) (string, error) { + value, err := redis.String(self.delegate.Do("GET", name)) + err = noErrNil(err) + return value, err +} + +func (self *RedigoConn) Set(name string, value string) (bool, error) { + reply, err := redis.String(self.delegate.Do("SET", name, value)) + err = noErrNil(err) + return err == nil && reply == "OK", nil +} + +func (self *RedigoConn) SetNX(name string, value string, expiry time.Duration) (bool, error) { + reply, err := redis.String(self.delegate.Do("SET", name, value, "NX", "PX", int(expiry/time.Millisecond))) + err = noErrNil(err) + return err == nil && reply == "OK", nil +} + +func (self *RedigoConn) PTTL(name string) (time.Duration, error) { + expiry, err := redis.Int64(self.delegate.Do("PTTL", name)) + err = noErrNil(err) + return time.Duration(expiry) * time.Millisecond, err +} + +func (self *RedigoConn) Eval(script *redsyncredis.Script, keysAndArgs ...interface{}) (interface{}, error) { + + v, err := self.delegate.Do("EVALSHA", script.Args(script.Hash, keysAndArgs)...) + if e, ok := err.(redis.Error); ok && strings.HasPrefix(string(e), "NOSCRIPT ") { + v, err = self.delegate.Do("EVAL", script.Args(script.Src, keysAndArgs)...) + } + return v, err + +} + +func (self *RedigoConn) Close() error { + err := self.delegate.Close() + return noErrNil(err) +} + +func noErrNil(err error) error { + + if err == redis.ErrNil { + return nil + } else { + return err + } +} diff --git a/redis/redigo/redigo_test.go b/redis/redigo/redigo_test.go new file mode 100644 index 0000000..9c7e60b --- /dev/null +++ b/redis/redigo/redigo_test.go @@ -0,0 +1,7 @@ +package redigo + +import "github.com/go-redsync/redsync/redis" + +var _ (redis.Conn) = (*RedigoConn)(nil) + +var _ (redis.Pool) = (*RedigoPool)(nil) diff --git a/redis/redis.go b/redis/redis.go new file mode 100644 index 0000000..bc980f2 --- /dev/null +++ b/redis/redis.go @@ -0,0 +1,49 @@ +package redis + +import ( + "crypto/sha1" + "encoding/hex" + "io" + "time" +) + +// A Pool maintains a pool of Redis connections. +type Pool interface { + Get() Conn +} + +type Conn interface { + Get(name string) (string, error) + Set(name string, value string) (bool, error) + SetNX(name string, value string, expiry time.Duration) (bool, error) + Eval(script *Script, keysAndArgs ...interface{}) (interface{}, error) + PTTL(name string) (time.Duration, error) + Close() error +} + +type Script struct { + KeyCount int + Src string + Hash string +} + +func NewScript(keyCount int, src string) *Script { + h := sha1.New() + io.WriteString(h, src) + return &Script{keyCount, src, hex.EncodeToString(h.Sum(nil))} +} + +func (self *Script) Args(spec string, keysAndArgs []interface{}) []interface{} { + var args []interface{} + if self.KeyCount < 0 { + args = make([]interface{}, 1+len(keysAndArgs)) + args[0] = spec + copy(args[1:], keysAndArgs) + } else { + args = make([]interface{}, 2+len(keysAndArgs)) + args[0] = spec + args[1] = self.KeyCount + copy(args[2:], keysAndArgs) + } + return args +} diff --git a/redis/redis_test.go b/redis/redis_test.go new file mode 100644 index 0000000..65a229e --- /dev/null +++ b/redis/redis_test.go @@ -0,0 +1 @@ +package redis diff --git a/redsync.go b/redsync.go index 51b7548..49ddce8 100644 --- a/redsync.go +++ b/redsync.go @@ -1,14 +1,17 @@ package redsync -import "time" +import ( + redsyncredis "github.com/go-redsync/redsync/redis" + "time" +) // Redsync provides a simple method for creating distributed mutexes using multiple Redis connection pools. type Redsync struct { - pools []Pool + pools []redsyncredis.Pool } // New creates and returns a new Redsync instance from given Redis connection pools. -func New(pools []Pool) *Redsync { +func New(pools []redsyncredis.Pool) *Redsync { return &Redsync{ pools: pools, } diff --git a/redsync_test.go b/redsync_test.go index b0b55dc..fecd5f0 100644 --- a/redsync_test.go +++ b/redsync_test.go @@ -1,14 +1,40 @@ package redsync import ( + goredislib "github.com/go-redis/redis" + "github.com/go-redsync/redsync/redis/goredis" + "github.com/go-redsync/redsync/redis/redigo" + redigolib "github.com/gomodule/redigo/redis" "os" "testing" + "time" + "github.com/go-redsync/redsync/redis" "github.com/stvp/tempredis" ) var servers []*tempredis.Server +type testCase struct { + poolCount int + pool []redis.Pool +} + +func makeCases(poolCount int) map[string]*testCase { + return map[string]*testCase{ + "redigo": { + poolCount, + newMockPoolsRedigo(poolCount), + }, + /* + "goredis": { + poolCount, + newMockPoolsGoredis(poolCount), + }, + */ + } +} + func TestMain(m *testing.M) { for i := 0; i < 8; i++ { server, err := tempredis.Start(tempredis.Config{}) @@ -25,14 +51,60 @@ func TestMain(m *testing.M) { } func TestRedsync(t *testing.T) { - pools := newMockPools(8) - rs := New(pools) - mutex := rs.NewMutex("test-redsync") - err := mutex.Lock() - if err != nil { + for k, v := range makeCases(8) { + t.Run(k, func(t *testing.T) { + rs := New(v.pool) + mutex := rs.NewMutex("test-redsync") + err := mutex.Lock() + if err != nil { + + } + + assertAcquired(t, v.pool, mutex) + }) } +} - assertAcquired(t, pools, mutex) +func newMockPoolsRedigo(n int) []redis.Pool { + pools := []redis.Pool{} + for _, server := range servers { + func(server *tempredis.Server) { + pools = append(pools, 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 + }, + })) + }(server) + if len(pools) == n { + break + } + } + return pools +} + +func newMockPoolsGoredis(n int) []redis.Pool { + pools := []redis.Pool{} + + for _, server := range servers { + func(server *tempredis.Server) { + + client := goredislib.NewClient(&goredislib.Options{ + Addr: server.Socket(), + }) + + pools = append(pools, goredis.NewGoredisPool(client)) + }(server) + if len(pools) == n { + break + } + } + return pools } From b272cf57deb0c30d433ae9cf940645f0fb694cfb Mon Sep 17 00:00:00 2001 From: Ben Tomasini Date: Fri, 14 Dec 2018 14:00:35 -0800 Subject: [PATCH 2/5] Fixed up tests to use separate pools of servers for each type of driver --- README.md | 7 +++++- examples/goredis/main.go | 36 ++++++++++++++++++++++++++++++ examples/redigo/main.go | 42 +++++++++++++++++++++++++++++++++++ mutex_test.go | 12 +++++----- redis/goredis/goredis.go | 16 +++++++++++-- redis/goredis/goredis_test.go | 7 ++++++ redis/redigo/redigo.go | 21 ++++++++++++++---- redis/redis.go | 15 ------------- redsync.go | 6 ++--- redsync_test.go | 37 ++++++++++++++++++++---------- 10 files changed, 156 insertions(+), 43 deletions(-) create mode 100644 examples/goredis/main.go create mode 100644 examples/redigo/main.go create mode 100644 redis/goredis/goredis_test.go diff --git a/README.md b/README.md index 3c58378..7334e61 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,12 @@ Install Redsync using the go get command: $ go get gopkg.in/redsync.v1 -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 diff --git a/examples/goredis/main.go b/examples/goredis/main.go new file mode 100644 index 0000000..aa26a67 --- /dev/null +++ b/examples/goredis/main.go @@ -0,0 +1,36 @@ +package main + +import ( + goredislib "github.com/go-redis/redis" + "github.com/go-redsync/redsync" + "github.com/go-redsync/redsync/redis" + "github.com/go-redsync/redsync/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() +} diff --git a/examples/redigo/main.go b/examples/redigo/main.go new file mode 100644 index 0000000..4ad7899 --- /dev/null +++ b/examples/redigo/main.go @@ -0,0 +1,42 @@ +package main + +import ( + "github.com/go-redsync/redsync" + "github.com/go-redsync/redsync/redis" + "github.com/go-redsync/redsync/redis/redigo" + redigolib "github.com/gomodule/redigo/redis" + "github.com/stvp/tempredis" + "time" +) + +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() +} diff --git a/mutex_test.go b/mutex_test.go index ed4a6b8..260a932 100644 --- a/mutex_test.go +++ b/mutex_test.go @@ -5,7 +5,7 @@ import ( "testing" "time" - redsyncredis "github.com/go-redsync/redsync/redis" + "github.com/go-redsync/redsync/redis" ) func TestMutex(t *testing.T) { @@ -92,7 +92,7 @@ func TestMutexQuorum(t *testing.T) { } } -func getPoolValues(pools []redsyncredis.Pool, name string) []string { +func getPoolValues(pools []redis.Pool, name string) []string { values := []string{} for _, pool := range pools { conn := pool.Get() @@ -106,7 +106,7 @@ func getPoolValues(pools []redsyncredis.Pool, name string) []string { return values } -func getPoolExpiries(pools []redsyncredis.Pool, name string) []int { +func getPoolExpiries(pools []redis.Pool, name string) []int { expiries := []int{} for _, pool := range pools { conn := pool.Get() @@ -120,7 +120,7 @@ func getPoolExpiries(pools []redsyncredis.Pool, name string) []int { return expiries } -func clogPools(pools []redsyncredis.Pool, mask int, mutex *Mutex) int { +func clogPools(pools []redis.Pool, mask int, mutex *Mutex) int { n := 0 for i, pool := range pools { if mask&(1< Date: Fri, 14 Dec 2018 14:02:09 -0800 Subject: [PATCH 3/5] Clean up docs --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7334e61..0d93aff 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,8 @@ Install Redsync using the go get command: 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). + * [Redigo](https://github.com/gomodule/redigo) + * [Go-redis](https://github.com/go-redis/redis) See the [examples](examples) folder for usage of each driver. From bc0851dfa16f8dcc9c537697b22db6f0f84a18cb Mon Sep 17 00:00:00 2001 From: Ben Tomasini Date: Mon, 17 Dec 2018 15:54:03 -0800 Subject: [PATCH 4/5] Changed module path --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index ac42908..bd3d2f3 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module github.com/go-redsync/redsync +module github.com/activatedio/redsync require ( github.com/go-redis/redis v6.14.2+incompatible From f693f2b2b09d847e4873d35385c96886a9f54c55 Mon Sep 17 00:00:00 2001 From: Ben Tomasini Date: Mon, 17 Dec 2018 15:59:48 -0800 Subject: [PATCH 5/5] Incremented version to v2 --- VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VERSION b/VERSION index 626799f..8c1384d 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -v1 +v2