Compare commits
No commits in common. "master" and "v1.0.0" have entirely different histories.
|
@ -1 +0,0 @@
|
||||||
tags
|
|
15
go.mod
15
go.mod
|
@ -1,13 +1,16 @@
|
||||||
module git.bit5.ru/backend/rdb
|
module github.com/bit.games/rdb
|
||||||
|
|
||||||
go 1.13
|
go 1.13
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.bit5.ru/backend/redigo v1.0.1
|
|
||||||
git.bit5.ru/backend/redsync v1.0.1
|
|
||||||
git.bit5.ru/backend/res_tracker v1.0.0
|
git.bit5.ru/backend/res_tracker v1.0.0
|
||||||
github.com/go-logr/logr v1.2.3
|
git.bit5.ru/backend/colog v1.0.0
|
||||||
github.com/go-logr/stdr v1.2.2
|
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/garyburd/redigo v1.6.4
|
||||||
|
github.com/gocraft/dbr v0.0.0-20190714181702-8114670a83bd // indirect
|
||||||
|
github.com/google/uuid v1.1.1 // indirect
|
||||||
|
github.com/gorilla/websocket v1.4.2 // indirect
|
||||||
|
github.com/hjr265/redsync v4.6.0
|
||||||
|
github.com/stretchr/testify v1.4.0
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
48
go.sum
48
go.sum
|
@ -1,28 +1,32 @@
|
||||||
git.bit5.ru/backend/redigo v1.0.1 h1:1LyyjHWfeed+0LEjMYqFnTuyr5ri2f+UDCV3vdAMh4Q=
|
github.com/DATA-DOG/go-sqlmock v1.3.3 h1:CWUqKXe0s8A2z6qCgkP4Kru7wC11YoAnoupUKFDnH08=
|
||||||
git.bit5.ru/backend/redigo v1.0.1/go.mod h1:nGfr55wovFNsbAleS5hMmtD/X3X5FZ52HJdbRses5WA=
|
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
|
||||||
git.bit5.ru/backend/redsync v1.0.1 h1:NcXwMw36riODqi6sMyvRCFVpIfRY63oNIGJ2szdaLoI=
|
|
||||||
git.bit5.ru/backend/redsync v1.0.1/go.mod h1:AUxVpYSlNCfOsx15g7/cBMIoAu8RYHGDohdD4yLpars=
|
|
||||||
git.bit5.ru/backend/res_tracker v1.0.0 h1:0FWwzP3yGOe9L39VuH9LIqyQABo/P+rd3kA112SvjHo=
|
|
||||||
git.bit5.ru/backend/res_tracker v1.0.0/go.mod h1:ffjnItxqkGc6rxOK9XgrQDirGhmIBwoqibmyLJ4TZtQ=
|
|
||||||
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/garyburd/redigo v1.6.0 h1:0VruCpn7yAIIu7pWVClQC8wxCJEcG3nyzpMSHKi1PQc=
|
||||||
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
|
github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
|
||||||
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA=
|
||||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
|
github.com/gocraft/dbr v0.0.0-20190714181702-8114670a83bd h1:GlmMPhEpMWrNOyUaAMpRGy4zkb03eXuTb8TKXr3j0dQ=
|
||||||
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
github.com/gocraft/dbr v0.0.0-20190714181702-8114670a83bd/go.mod h1:BK1nFI5Pp8XJg1sE7oMBzyW32LBuS2r25HlZPa6tXXs=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
|
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA=
|
||||||
|
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks=
|
||||||
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
|
||||||
|
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
|
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
|
||||||
|
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
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/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203 h1:QVqDTf3h2WHt08YuiTGPZLls0Wq99X9bWd0Q5ZSBesM=
|
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||||
github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKNihBbwlX8dLpwxCl3+HnXKV/R0e+sRLd9C8=
|
|
||||||
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/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
|
|
141
rdb.go
141
rdb.go
|
@ -4,13 +4,13 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.bit5.ru/backend/redigo/redis"
|
"git.bit5.ru/backend/colog"
|
||||||
"git.bit5.ru/backend/redsync"
|
|
||||||
"git.bit5.ru/backend/res_tracker"
|
"git.bit5.ru/backend/res_tracker"
|
||||||
|
"github.com/garyburd/redigo/redis"
|
||||||
"github.com/go-logr/logr"
|
"github.com/hjr265/redsync"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -18,59 +18,24 @@ const (
|
||||||
ExpireRDMutexSec = 30
|
ExpireRDMutexSec = 30
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var pools sync.Map
|
||||||
|
|
||||||
type RdSettings struct {
|
type RdSettings struct {
|
||||||
Host, Prefix string
|
Host, Prefix string
|
||||||
//will be shown in CLIENT LIST
|
|
||||||
ClientName string
|
|
||||||
Port int
|
Port int
|
||||||
Db int
|
Db int
|
||||||
LogLevel int
|
LogLevel int
|
||||||
MaxIdle int
|
|
||||||
IdleTimeoutSec int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *RdSettings) ConnStr() string {
|
func (s *RdSettings) ConnStr() string {
|
||||||
return s.Host + ":" + strconv.Itoa(s.Port)
|
return s.Host + ":" + strconv.Itoa(s.Port)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Pool struct {
|
// NOTE: redis connection logs all operations
|
||||||
S RdSettings
|
|
||||||
RP *redis.Pool
|
|
||||||
}
|
|
||||||
|
|
||||||
func OpenPool(s RdSettings, logger logr.Logger) *Pool {
|
|
||||||
p := &Pool{S: s, RP: newRedisPool(s, logger)}
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pool) Close() {
|
|
||||||
p.RP.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Pool) Get() redis.Conn {
|
|
||||||
conn := p.RP.Get()
|
|
||||||
|
|
||||||
if res_tracker.IsOn() {
|
|
||||||
//let's wrap our connection with the special tracked wrapper
|
|
||||||
conn = &tracked{conn}
|
|
||||||
res_tracker.Track(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
return conn
|
|
||||||
}
|
|
||||||
|
|
||||||
//NOTE: convenience method for 'one-shot' commands
|
|
||||||
func (p *Pool) Do(cmd string, args ...interface{}) (interface{}, error) {
|
|
||||||
rc := p.Get()
|
|
||||||
defer rc.Close()
|
|
||||||
return rc.Do(cmd, args...)
|
|
||||||
}
|
|
||||||
|
|
||||||
//NOTE: redis connection logs all operations
|
|
||||||
type rdb struct {
|
type rdb struct {
|
||||||
orig redis.Conn
|
orig redis.Conn
|
||||||
name string
|
name string
|
||||||
logger logr.Logger
|
logger *colog.CoLog
|
||||||
s RdSettings
|
s RdSettings
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +58,7 @@ func (rd *rdb) Do(command string, args ...interface{}) (interface{}, error) {
|
||||||
for i := 0; i < len(args); i++ {
|
for i := 0; i < len(args); i++ {
|
||||||
s += fmt.Sprintf("%v ", args[i])
|
s += fmt.Sprintf("%v ", args[i])
|
||||||
}
|
}
|
||||||
rd.logger.WithCallDepth(2).V(1).Info(command + " " + s)
|
rd.logger.Output(colog.LDebug, 5, fmt.Sprintf("%s %s", command, s))
|
||||||
}
|
}
|
||||||
} else if rd.s.LogLevel > 0 {
|
} else if rd.s.LogLevel > 0 {
|
||||||
//for this level not logging too verbose commands
|
//for this level not logging too verbose commands
|
||||||
|
@ -105,7 +70,7 @@ func (rd *rdb) Do(command string, args ...interface{}) (interface{}, error) {
|
||||||
if len(args) > 5 {
|
if len(args) > 5 {
|
||||||
s += " ..."
|
s += " ..."
|
||||||
}
|
}
|
||||||
rd.logger.WithCallDepth(2).V(1).Info(command + " " + s)
|
rd.logger.Output(colog.LDebug, 5, fmt.Sprintf("%s %s", command, s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rd.orig.Do(command, args...)
|
return rd.orig.Do(command, args...)
|
||||||
|
@ -118,7 +83,7 @@ func (rd *rdb) Send(command string, args ...interface{}) error {
|
||||||
for i := 0; i < len(args); i++ {
|
for i := 0; i < len(args); i++ {
|
||||||
s += fmt.Sprintf("%v ", args[i])
|
s += fmt.Sprintf("%v ", args[i])
|
||||||
}
|
}
|
||||||
rd.logger.WithCallDepth(2).V(1).Info(command + " " + s)
|
rd.logger.Output(colog.LDebug, 5, fmt.Sprintf("%s %s", command, s))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rd.orig.Send(command, args...)
|
return rd.orig.Send(command, args...)
|
||||||
|
@ -128,44 +93,44 @@ func (rd *rdb) Receive() (interface{}, error) {
|
||||||
return rd.orig.Receive()
|
return rd.orig.Receive()
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRedisPool(s RdSettings, logger logr.Logger) *redis.Pool {
|
func redisPool(logger *colog.CoLog, s RdSettings, clientName string) *redis.Pool {
|
||||||
|
//TODO: why not simply using s as a key for pools.Load(..)?
|
||||||
maxIdle := s.MaxIdle
|
key := s.Host + ":" + strconv.Itoa(s.Port) + ":" + strconv.Itoa(s.Db) + ":" + s.Prefix
|
||||||
if maxIdle == 0 {
|
v, ok := pools.Load(key)
|
||||||
maxIdle = 16
|
if ok {
|
||||||
|
return v.(*redis.Pool)
|
||||||
|
} else {
|
||||||
|
rdpool := NewRedisPool(logger, s, clientName)
|
||||||
|
pools.Store(key, rdpool)
|
||||||
|
return rdpool
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
idleTimeoutSec := s.IdleTimeoutSec
|
func NewRedisPool(logger *colog.CoLog, s RdSettings, clientName string) *redis.Pool {
|
||||||
if idleTimeoutSec == 0 {
|
return NewRedisPoolEx(logger, s, 16, 240*time.Second, clientName)
|
||||||
idleTimeoutSec = 240
|
}
|
||||||
}
|
|
||||||
|
|
||||||
connStr := s.ConnStr()
|
|
||||||
|
|
||||||
if len(s.Prefix) > 0 {
|
|
||||||
logger = logger.WithValues("rd", s.Prefix)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
func NewRedisPoolEx(logger *colog.CoLog, s RdSettings, maxIdle int, idleTimeout time.Duration, clientName string) *redis.Pool {
|
||||||
return &redis.Pool{
|
return &redis.Pool{
|
||||||
Wait: false,
|
Wait: false,
|
||||||
MaxIdle: maxIdle,
|
MaxIdle: maxIdle,
|
||||||
IdleTimeout: time.Second * time.Duration(idleTimeoutSec),
|
IdleTimeout: idleTimeout,
|
||||||
Dial: func() (redis.Conn, error) {
|
Dial: func() (redis.Conn, error) {
|
||||||
orig, err := redis.Dial("tcp", connStr)
|
orig, err := redis.Dial("tcp", s.ConnStr())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
c := &rdb{
|
c := &rdb{
|
||||||
orig: orig,
|
orig: orig,
|
||||||
name: s.Prefix,
|
name: s.Prefix,
|
||||||
logger: logger,
|
logger: logger.Clone().AddPrefix("[" + s.Prefix + "] "),
|
||||||
s: s,
|
s: s,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Сохраняем название клиента для диагностики соединений с помощью команды CLIENT LIST.
|
// Сохраняем название клиента для диагностики соединений с помощью команды CLIENT LIST.
|
||||||
// https://redis.io/commands/client-list/
|
// https://redis.io/commands/client-list/
|
||||||
if len(s.ClientName) > 0 {
|
if len(clientName) > 0 {
|
||||||
_, err = c.Do("CLIENT", "SETNAME", s.ClientName)
|
_, err = c.Do("CLIENT", "SETNAME", clientName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
@ -178,34 +143,44 @@ func newRedisPool(s RdSettings, logger logr.Logger) *redis.Pool {
|
||||||
|
|
||||||
return c, err
|
return c, err
|
||||||
},
|
},
|
||||||
TestOnBorrow: func(c redis.Conn, _ time.Time) error {
|
TestOnBorrow: func(c redis.Conn, t time.Time) error {
|
||||||
_, err := c.Do("PING")
|
_, err := c.Do("PING")
|
||||||
return err
|
return err
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRedisMutex(pool *Pool, name string, ttlSec int) *redsync.Mutex {
|
func GetRedisConn(logger *colog.CoLog, s RdSettings, clientName string) redis.Conn {
|
||||||
mx, _ := redsync.NewMutexWithPool(name, []*redis.Pool{pool.RP})
|
conn := redisPool(logger, s, clientName).Get()
|
||||||
|
|
||||||
|
if res_tracker.IsOn() {
|
||||||
|
//let's wrap our connection with the special tracked wrapper
|
||||||
|
conn = tracked{conn}
|
||||||
|
res_tracker.Track(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRedisMutex(logger *colog.CoLog, s RdSettings, name string, ttlSec int) *redsync.Mutex {
|
||||||
|
mx, _ := redsync.NewMutexWithPool(name, []*redis.Pool{redisPool(logger, s, "")})
|
||||||
mx.Expiry = time.Duration(ttlSec) * time.Second
|
mx.Expiry = time.Duration(ttlSec) * time.Second
|
||||||
return mx
|
return mx
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetRedisMutexAutoTTL(pool *Pool, name string) *redsync.Mutex {
|
func GetRedisMutexAutoTTL(logger *colog.CoLog, s RdSettings, name string) *redsync.Mutex {
|
||||||
return GetRedisMutex(pool, name, ExpireRDMutexSec)
|
return GetRedisMutex(logger, s, name, ExpireRDMutexSec)
|
||||||
}
|
}
|
||||||
|
|
||||||
func RemoveRedisMutex(pool *Pool, name string) error {
|
func RemoveRedisMutex(logger *colog.CoLog, s RdSettings, name string) error {
|
||||||
rd := pool.Get()
|
rd := redisPool(logger, s, "").Get()
|
||||||
defer rd.Close()
|
|
||||||
|
|
||||||
_, err := rd.Do("DEL", name)
|
_, err := rd.Do("DEL", name)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExistsRedisMutex(pool *Pool, name string) (bool, error) {
|
func ExistsRedisMutex(logger *colog.CoLog, s RdSettings, name string) (bool, error) {
|
||||||
rd := pool.Get()
|
rd := redisPool(logger, s, "").Get()
|
||||||
defer rd.Close()
|
|
||||||
|
|
||||||
exists, err := redis.Bool(rd.Do("EXISTS", name))
|
exists, err := redis.Bool(rd.Do("EXISTS", name))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -409,14 +384,14 @@ type tracked struct {
|
||||||
subj redis.Conn
|
subj redis.Conn
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tracked) Close() error {
|
func (t tracked) Close() error {
|
||||||
res_tracker.Untrack(t)
|
res_tracker.Untrack(t)
|
||||||
return t.subj.Close()
|
return t.subj.Close()
|
||||||
}
|
}
|
||||||
func (t *tracked) Do(cmd string, args ...interface{}) (interface{}, error) {
|
func (t tracked) Do(cmd string, args ...interface{}) (interface{}, error) {
|
||||||
return t.subj.Do(cmd, args...)
|
return t.subj.Do(cmd, args...)
|
||||||
}
|
}
|
||||||
func (t *tracked) Send(cmd string, args ...interface{}) error { return t.subj.Send(cmd, args...) }
|
func (t tracked) Send(cmd string, args ...interface{}) error { return t.subj.Send(cmd, args...) }
|
||||||
func (t *tracked) Err() error { return t.subj.Err() }
|
func (t tracked) Err() error { return t.subj.Err() }
|
||||||
func (t *tracked) Flush() error { return t.subj.Flush() }
|
func (t tracked) Flush() error { return t.subj.Flush() }
|
||||||
func (t *tracked) Receive() (interface{}, error) { return t.subj.Receive() }
|
func (t tracked) Receive() (interface{}, error) { return t.subj.Receive() }
|
||||||
|
|
53
rdb_test.go
53
rdb_test.go
|
@ -1,33 +1,30 @@
|
||||||
package rdb_test
|
package rdb_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"git.bit5.ru/backend/colog"
|
||||||
"git.bit5.ru/backend/rdb"
|
"git.bit5.ru/backend/rdb"
|
||||||
|
"github.com/garyburd/redigo/redis"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"github.com/go-logr/logr"
|
|
||||||
"github.com/go-logr/stdr"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const verbosity = 0
|
func getPool() *redis.Pool {
|
||||||
|
pool := rdb.NewRedisPool(getLogger(), rdb.RdSettings{Host: "localhost", Port: 6379, Db: 10}, "test")
|
||||||
func getPool() *rdb.Pool {
|
|
||||||
//TODO: use ENV settings as well
|
|
||||||
pool := rdb.OpenPool(rdb.RdSettings{Host: "localhost", Port: 6379, Db: 10, ClientName: "test", LogLevel: verbosity}, getLogger())
|
|
||||||
return pool
|
return pool
|
||||||
}
|
}
|
||||||
|
|
||||||
func getLogger() logr.Logger {
|
func getLogger() *colog.CoLog {
|
||||||
//TODO: use ENV settings as well
|
tlog := colog.NewCoLog(os.Stderr, "", 0)
|
||||||
stdr.SetVerbosity(verbosity)
|
ft := &colog.StdFormatter{Flag: 0}
|
||||||
return stdr.New(log.New(os.Stdout, "", log.Lshortfile))
|
ft.ColorSupported(true)
|
||||||
|
tlog.SetFormatter(ft)
|
||||||
|
return tlog
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBadConnection(t *testing.T) {
|
func TestBadConnection(t *testing.T) {
|
||||||
pool := rdb.OpenPool(rdb.RdSettings{Host: "dummy", Port: 80, ClientName: "test"}, getLogger())
|
pool := rdb.NewRedisPool(getLogger(), rdb.RdSettings{Host: "dummy", Port: 80}, "test")
|
||||||
conn := pool.Get()
|
conn := pool.Get()
|
||||||
assert.NotNil(t, conn)
|
assert.NotNil(t, conn)
|
||||||
_, err := conn.Do("PING")
|
_, err := conn.Do("PING")
|
||||||
|
@ -36,56 +33,38 @@ func TestBadConnection(t *testing.T) {
|
||||||
|
|
||||||
func TestGetConn(t *testing.T) {
|
func TestGetConn(t *testing.T) {
|
||||||
pool := getPool()
|
pool := getPool()
|
||||||
defer pool.Close()
|
|
||||||
|
|
||||||
conn := pool.Get()
|
conn := pool.Get()
|
||||||
defer conn.Close()
|
defer conn.Close()
|
||||||
|
|
||||||
_, err := conn.Do("PING")
|
_, err := conn.Do("PING")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCloseConn(t *testing.T) {
|
func TestCloseConn(t *testing.T) {
|
||||||
pool := getPool()
|
pool := getPool()
|
||||||
assert.EqualValues(t, 0, pool.RP.IdleCount())
|
|
||||||
defer pool.Close()
|
|
||||||
|
|
||||||
conn := pool.Get()
|
conn := pool.Get()
|
||||||
assert.EqualValues(t, 0, pool.RP.IdleCount())
|
assert.EqualValues(t, 0, pool.IdleCount())
|
||||||
|
|
||||||
_, err := conn.Do("PING")
|
_, err := conn.Do("PING")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
conn.Close()
|
conn.Close()
|
||||||
assert.EqualValues(t, 1, pool.RP.IdleCount())
|
|
||||||
|
|
||||||
_, err = conn.Do("PING")
|
_, err = conn.Do("PING")
|
||||||
assert.NotNil(t, err)
|
assert.NotNil(t, err)
|
||||||
|
assert.EqualValues(t, 1, pool.IdleCount())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDoubleCloseConnIsOk(t *testing.T) {
|
func TestDoubleCloseConnIsOk(t *testing.T) {
|
||||||
pool := getPool()
|
pool := getPool()
|
||||||
defer pool.Close()
|
|
||||||
|
|
||||||
conn := pool.Get()
|
conn := pool.Get()
|
||||||
assert.EqualValues(t, 0, pool.RP.IdleCount())
|
|
||||||
|
|
||||||
_, err := conn.Do("PING")
|
_, err := conn.Do("PING")
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|
||||||
assert.EqualValues(t, 0, pool.RP.IdleCount())
|
assert.EqualValues(t, 0, pool.IdleCount())
|
||||||
conn.Close()
|
conn.Close()
|
||||||
assert.EqualValues(t, 1, pool.RP.IdleCount())
|
assert.EqualValues(t, 1, pool.IdleCount())
|
||||||
conn.Close()
|
conn.Close()
|
||||||
assert.EqualValues(t, 1, pool.RP.IdleCount())
|
assert.EqualValues(t, 1, pool.IdleCount())
|
||||||
}
|
|
||||||
|
|
||||||
func TestDoOnPool(t *testing.T) {
|
|
||||||
pool := getPool()
|
|
||||||
defer pool.Close()
|
|
||||||
|
|
||||||
assert.EqualValues(t, 0, pool.RP.IdleCount())
|
|
||||||
_, err := pool.Do("PING")
|
|
||||||
assert.EqualValues(t, 1, pool.RP.IdleCount())
|
|
||||||
assert.Nil(t, err)
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue