Vendor update
This commit is contained in:
parent
8ebe5f6a02
commit
e5f062ee91
2
vendor/github.com/thehowl/go-osuapi/osubool.go
generated
vendored
2
vendor/github.com/thehowl/go-osuapi/osubool.go
generated
vendored
|
@ -9,7 +9,7 @@ type OsuBool bool
|
||||||
|
|
||||||
// UnmarshalJSON converts `"0"` to false and `"1"` to true.
|
// UnmarshalJSON converts `"0"` to false and `"1"` to true.
|
||||||
func (o *OsuBool) UnmarshalJSON(data []byte) error {
|
func (o *OsuBool) UnmarshalJSON(data []byte) error {
|
||||||
if string(data) == `"0"` {
|
if string(data) == `0` {
|
||||||
*o = false
|
*o = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
1
vendor/gopkg.in/redis.v5/Makefile
generated
vendored
1
vendor/gopkg.in/redis.v5/Makefile
generated
vendored
|
@ -15,4 +15,5 @@ testdata/redis:
|
||||||
wget -qO- https://github.com/antirez/redis/archive/unstable.tar.gz | tar xvz --strip-components=1 -C $@
|
wget -qO- https://github.com/antirez/redis/archive/unstable.tar.gz | tar xvz --strip-components=1 -C $@
|
||||||
|
|
||||||
testdata/redis/src/redis-server: testdata/redis
|
testdata/redis/src/redis-server: testdata/redis
|
||||||
|
sed -i 's/libjemalloc.a/libjemalloc.a -lrt/g' $</src/Makefile
|
||||||
cd $< && make all
|
cd $< && make all
|
||||||
|
|
101
vendor/gopkg.in/redis.v5/cluster.go
generated
vendored
101
vendor/gopkg.in/redis.v5/cluster.go
generated
vendored
|
@ -14,6 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var errClusterNoNodes = internal.RedisError("redis: cluster has no nodes")
|
var errClusterNoNodes = internal.RedisError("redis: cluster has no nodes")
|
||||||
|
var errNilClusterState = internal.RedisError("redis: cannot load cluster slots")
|
||||||
|
|
||||||
// ClusterOptions are used to configure a cluster client and should be
|
// ClusterOptions are used to configure a cluster client and should be
|
||||||
// passed to NewClusterClient.
|
// passed to NewClusterClient.
|
||||||
|
@ -355,7 +356,14 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient {
|
||||||
_, _ = c.nodes.Get(addr)
|
_, _ = c.nodes.Get(addr)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.reloadSlots()
|
// Preload cluster slots.
|
||||||
|
for i := 0; i < 10; i++ {
|
||||||
|
state, err := c.reloadSlots()
|
||||||
|
if err == nil {
|
||||||
|
c._state.Store(state)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if opt.IdleCheckFrequency > 0 {
|
if opt.IdleCheckFrequency > 0 {
|
||||||
go c.reaper(opt.IdleCheckFrequency)
|
go c.reaper(opt.IdleCheckFrequency)
|
||||||
|
@ -366,10 +374,11 @@ func NewClusterClient(opt *ClusterOptions) *ClusterClient {
|
||||||
|
|
||||||
func (c *ClusterClient) state() *clusterState {
|
func (c *ClusterClient) state() *clusterState {
|
||||||
v := c._state.Load()
|
v := c._state.Load()
|
||||||
if v == nil {
|
if v != nil {
|
||||||
return nil
|
return v.(*clusterState)
|
||||||
}
|
}
|
||||||
return v.(*clusterState)
|
c.lazyReloadSlots()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *clusterNode, error) {
|
func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *clusterNode, error) {
|
||||||
|
@ -397,10 +406,12 @@ func (c *ClusterClient) cmdSlotAndNode(state *clusterState, cmd Cmder) (int, *cl
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error {
|
func (c *ClusterClient) Watch(fn func(*Tx) error, keys ...string) error {
|
||||||
|
state := c.state()
|
||||||
|
|
||||||
var node *clusterNode
|
var node *clusterNode
|
||||||
var err error
|
var err error
|
||||||
if len(keys) > 0 {
|
if state != nil && len(keys) > 0 {
|
||||||
node, err = c.state().slotMasterNode(hashtag.Slot(keys[0]))
|
node, err = state.slotMasterNode(hashtag.Slot(keys[0]))
|
||||||
} else {
|
} else {
|
||||||
node, err = c.nodes.Random()
|
node, err = c.nodes.Random()
|
||||||
}
|
}
|
||||||
|
@ -463,8 +474,9 @@ func (c *ClusterClient) Process(cmd Cmder) error {
|
||||||
var addr string
|
var addr string
|
||||||
moved, ask, addr = internal.IsMovedError(err)
|
moved, ask, addr = internal.IsMovedError(err)
|
||||||
if moved || ask {
|
if moved || ask {
|
||||||
if slot >= 0 {
|
state := c.state()
|
||||||
master, _ := c.state().slotMasterNode(slot)
|
if state != nil && slot >= 0 {
|
||||||
|
master, _ := state.slotMasterNode(slot)
|
||||||
if moved && (master == nil || master.Client.getAddr() != addr) {
|
if moved && (master == nil || master.Client.getAddr() != addr) {
|
||||||
c.lazyReloadSlots()
|
c.lazyReloadSlots()
|
||||||
}
|
}
|
||||||
|
@ -523,7 +535,7 @@ func (c *ClusterClient) ForEachNode(fn func(client *Client) error) error {
|
||||||
func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error {
|
func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error {
|
||||||
state := c.state()
|
state := c.state()
|
||||||
if state == nil {
|
if state == nil {
|
||||||
return nil
|
return errNilClusterState
|
||||||
}
|
}
|
||||||
|
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
@ -564,12 +576,13 @@ func (c *ClusterClient) ForEachMaster(fn func(client *Client) error) error {
|
||||||
|
|
||||||
// PoolStats returns accumulated connection pool stats.
|
// PoolStats returns accumulated connection pool stats.
|
||||||
func (c *ClusterClient) PoolStats() *PoolStats {
|
func (c *ClusterClient) PoolStats() *PoolStats {
|
||||||
|
var acc PoolStats
|
||||||
|
|
||||||
nodes, err := c.nodes.All()
|
nodes, err := c.nodes.All()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return &acc
|
||||||
}
|
}
|
||||||
|
|
||||||
var acc PoolStats
|
|
||||||
for _, node := range nodes {
|
for _, node := range nodes {
|
||||||
s := node.Client.connPool.Stats()
|
s := node.Client.connPool.Stats()
|
||||||
acc.Requests += s.Requests
|
acc.Requests += s.Requests
|
||||||
|
@ -585,37 +598,46 @@ func (c *ClusterClient) lazyReloadSlots() {
|
||||||
if !atomic.CompareAndSwapUint32(&c.reloading, 0, 1) {
|
if !atomic.CompareAndSwapUint32(&c.reloading, 0, 1) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
c.reloadSlots()
|
for i := 0; i < 1000; i++ {
|
||||||
|
state, err := c.reloadSlots()
|
||||||
|
if err == pool.ErrClosed {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if err == nil {
|
||||||
|
c._state.Store(state)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
time.Sleep(time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
time.Sleep(3 * time.Second)
|
||||||
atomic.StoreUint32(&c.reloading, 0)
|
atomic.StoreUint32(&c.reloading, 0)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ClusterClient) reloadSlots() {
|
func (c *ClusterClient) reloadSlots() (*clusterState, error) {
|
||||||
for i := 0; i < 10; i++ {
|
node, err := c.nodes.Random()
|
||||||
node, err := c.nodes.Random()
|
if err != nil {
|
||||||
if err != nil {
|
return nil, err
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.cmds == nil {
|
|
||||||
cmds, err := node.Client.Command().Result()
|
|
||||||
if err == nil {
|
|
||||||
c.cmds = cmds
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
slots, err := node.Client.ClusterSlots().Result()
|
|
||||||
if err != nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
state, err := newClusterState(c.nodes, slots)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c._state.Store(state)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: fix race
|
||||||
|
if c.cmds == nil {
|
||||||
|
cmds, err := node.Client.Command().Result()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
c.cmds = cmds
|
||||||
|
}
|
||||||
|
|
||||||
|
slots, err := node.Client.ClusterSlots().Result()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return newClusterState(c.nodes, slots)
|
||||||
}
|
}
|
||||||
|
|
||||||
// reaper closes idle connections to the cluster.
|
// reaper closes idle connections to the cluster.
|
||||||
|
@ -789,8 +811,13 @@ func (c *ClusterClient) txPipelineExec(cmds []Cmder) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state := c.state()
|
||||||
|
if state == nil {
|
||||||
|
return errNilClusterState
|
||||||
|
}
|
||||||
|
|
||||||
for slot, cmds := range cmdsMap {
|
for slot, cmds := range cmdsMap {
|
||||||
node, err := c.state().slotMasterNode(slot)
|
node, err := state.slotMasterNode(slot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
setCmdsErr(cmds, err)
|
setCmdsErr(cmds, err)
|
||||||
continue
|
continue
|
||||||
|
|
8
vendor/gopkg.in/redis.v5/command.go
generated
vendored
8
vendor/gopkg.in/redis.v5/command.go
generated
vendored
|
@ -58,7 +58,7 @@ func writeCmd(cn *pool.Conn, cmds ...Cmder) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := cn.NetConn.Write(cn.Wb.Bytes())
|
_, err := cn.Write(cn.Wb.Bytes())
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,7 +445,7 @@ func (cmd *StringCmd) Result() (string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *StringCmd) Bytes() ([]byte, error) {
|
func (cmd *StringCmd) Bytes() ([]byte, error) {
|
||||||
return []byte(cmd.val), cmd.err
|
return cmd.val, cmd.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cmd *StringCmd) Int64() (int64, error) {
|
func (cmd *StringCmd) Int64() (int64, error) {
|
||||||
|
@ -542,6 +542,10 @@ func (cmd *StringSliceCmd) String() string {
|
||||||
return cmdString(cmd, cmd.val)
|
return cmdString(cmd, cmd.val)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cmd *StringSliceCmd) ScanSlice(container interface{}) error {
|
||||||
|
return proto.ScanSlice(cmd.Val(), container)
|
||||||
|
}
|
||||||
|
|
||||||
func (cmd *StringSliceCmd) readReply(cn *pool.Conn) error {
|
func (cmd *StringSliceCmd) readReply(cn *pool.Conn) error {
|
||||||
var v interface{}
|
var v interface{}
|
||||||
v, cmd.err = cn.Rd.ReadArrayReply(stringSliceParser)
|
v, cmd.err = cn.Rd.ReadArrayReply(stringSliceParser)
|
||||||
|
|
64
vendor/gopkg.in/redis.v5/commands.go
generated
vendored
64
vendor/gopkg.in/redis.v5/commands.go
generated
vendored
|
@ -50,14 +50,16 @@ type Cmdable interface {
|
||||||
Unlink(keys ...string) *IntCmd
|
Unlink(keys ...string) *IntCmd
|
||||||
Dump(key string) *StringCmd
|
Dump(key string) *StringCmd
|
||||||
Exists(key string) *BoolCmd
|
Exists(key string) *BoolCmd
|
||||||
|
// TODO: merge with Exists in v6
|
||||||
|
ExistsMulti(keys ...string) *IntCmd
|
||||||
Expire(key string, expiration time.Duration) *BoolCmd
|
Expire(key string, expiration time.Duration) *BoolCmd
|
||||||
ExpireAt(key string, tm time.Time) *BoolCmd
|
ExpireAt(key string, tm time.Time) *BoolCmd
|
||||||
Keys(pattern string) *StringSliceCmd
|
Keys(pattern string) *StringSliceCmd
|
||||||
Migrate(host, port, key string, db int64, timeout time.Duration) *StatusCmd
|
Migrate(host, port, key string, db int64, timeout time.Duration) *StatusCmd
|
||||||
Move(key string, db int64) *BoolCmd
|
Move(key string, db int64) *BoolCmd
|
||||||
ObjectRefCount(keys ...string) *IntCmd
|
ObjectRefCount(key string) *IntCmd
|
||||||
ObjectEncoding(keys ...string) *StringCmd
|
ObjectEncoding(key string) *StringCmd
|
||||||
ObjectIdleTime(keys ...string) *DurationCmd
|
ObjectIdleTime(key string) *DurationCmd
|
||||||
Persist(key string) *BoolCmd
|
Persist(key string) *BoolCmd
|
||||||
PExpire(key string, expiration time.Duration) *BoolCmd
|
PExpire(key string, expiration time.Duration) *BoolCmd
|
||||||
PExpireAt(key string, tm time.Time) *BoolCmd
|
PExpireAt(key string, tm time.Time) *BoolCmd
|
||||||
|
@ -170,6 +172,7 @@ type Cmdable interface {
|
||||||
ZRem(key string, members ...interface{}) *IntCmd
|
ZRem(key string, members ...interface{}) *IntCmd
|
||||||
ZRemRangeByRank(key string, start, stop int64) *IntCmd
|
ZRemRangeByRank(key string, start, stop int64) *IntCmd
|
||||||
ZRemRangeByScore(key, min, max string) *IntCmd
|
ZRemRangeByScore(key, min, max string) *IntCmd
|
||||||
|
ZRemRangeByLex(key, min, max string) *IntCmd
|
||||||
ZRevRange(key string, start, stop int64) *StringSliceCmd
|
ZRevRange(key string, start, stop int64) *StringSliceCmd
|
||||||
ZRevRangeWithScores(key string, start, stop int64) *ZSliceCmd
|
ZRevRangeWithScores(key string, start, stop int64) *ZSliceCmd
|
||||||
ZRevRangeByScore(key string, opt ZRangeBy) *StringSliceCmd
|
ZRevRangeByScore(key string, opt ZRangeBy) *StringSliceCmd
|
||||||
|
@ -270,6 +273,13 @@ func (c *cmdable) Ping() *StatusCmd {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *cmdable) Wait(numSlaves int, timeout time.Duration) *IntCmd {
|
||||||
|
|
||||||
|
cmd := NewIntCmd("wait", numSlaves, int(timeout/time.Millisecond))
|
||||||
|
c.process(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func (c *cmdable) Quit() *StatusCmd {
|
func (c *cmdable) Quit() *StatusCmd {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
@ -316,6 +326,17 @@ func (c *cmdable) Exists(key string) *BoolCmd {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *cmdable) ExistsMulti(keys ...string) *IntCmd {
|
||||||
|
args := make([]interface{}, 1+len(keys))
|
||||||
|
args[0] = "exists"
|
||||||
|
for i, key := range keys {
|
||||||
|
args[1+i] = key
|
||||||
|
}
|
||||||
|
cmd := NewIntCmd(args...)
|
||||||
|
c.process(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func (c *cmdable) Expire(key string, expiration time.Duration) *BoolCmd {
|
func (c *cmdable) Expire(key string, expiration time.Duration) *BoolCmd {
|
||||||
cmd := NewBoolCmd("expire", key, formatSec(expiration))
|
cmd := NewBoolCmd("expire", key, formatSec(expiration))
|
||||||
c.process(cmd)
|
c.process(cmd)
|
||||||
|
@ -354,38 +375,20 @@ func (c *cmdable) Move(key string, db int64) *BoolCmd {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cmdable) ObjectRefCount(keys ...string) *IntCmd {
|
func (c *cmdable) ObjectRefCount(key string) *IntCmd {
|
||||||
args := make([]interface{}, 2+len(keys))
|
cmd := NewIntCmd("object", "refcount", key)
|
||||||
args[0] = "object"
|
|
||||||
args[1] = "refcount"
|
|
||||||
for i, key := range keys {
|
|
||||||
args[2+i] = key
|
|
||||||
}
|
|
||||||
cmd := NewIntCmd(args...)
|
|
||||||
c.process(cmd)
|
c.process(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cmdable) ObjectEncoding(keys ...string) *StringCmd {
|
func (c *cmdable) ObjectEncoding(key string) *StringCmd {
|
||||||
args := make([]interface{}, 2+len(keys))
|
cmd := NewStringCmd("object", "encoding", key)
|
||||||
args[0] = "object"
|
|
||||||
args[1] = "encoding"
|
|
||||||
for i, key := range keys {
|
|
||||||
args[2+i] = key
|
|
||||||
}
|
|
||||||
cmd := NewStringCmd(args...)
|
|
||||||
c.process(cmd)
|
c.process(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cmdable) ObjectIdleTime(keys ...string) *DurationCmd {
|
func (c *cmdable) ObjectIdleTime(key string) *DurationCmd {
|
||||||
args := make([]interface{}, 2+len(keys))
|
cmd := NewDurationCmd(time.Second, "object", "idletime", key)
|
||||||
args[0] = "object"
|
|
||||||
args[1] = "idletime"
|
|
||||||
for i, key := range keys {
|
|
||||||
args[2+i] = key
|
|
||||||
}
|
|
||||||
cmd := NewDurationCmd(time.Second, args...)
|
|
||||||
c.process(cmd)
|
c.process(cmd)
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -731,6 +734,7 @@ func (c *cmdable) MSetNX(pairs ...interface{}) *BoolCmd {
|
||||||
|
|
||||||
// Redis `SET key value [expiration]` command.
|
// Redis `SET key value [expiration]` command.
|
||||||
//
|
//
|
||||||
|
// Use expiration for `SETEX`-like behavior.
|
||||||
// Zero expiration means the key has no expiration time.
|
// Zero expiration means the key has no expiration time.
|
||||||
func (c *cmdable) Set(key string, value interface{}, expiration time.Duration) *StatusCmd {
|
func (c *cmdable) Set(key string, value interface{}, expiration time.Duration) *StatusCmd {
|
||||||
args := make([]interface{}, 3, 4)
|
args := make([]interface{}, 3, 4)
|
||||||
|
@ -1468,6 +1472,12 @@ func (c *cmdable) ZRemRangeByScore(key, min, max string) *IntCmd {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *cmdable) ZRemRangeByLex(key, min, max string) *IntCmd {
|
||||||
|
cmd := NewIntCmd("zremrangebylex", key, min, max)
|
||||||
|
c.process(cmd)
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func (c *cmdable) ZRevRange(key string, start, stop int64) *StringSliceCmd {
|
func (c *cmdable) ZRevRange(key string, start, stop int64) *StringSliceCmd {
|
||||||
cmd := NewStringSliceCmd("zrevrange", key, start, stop)
|
cmd := NewStringSliceCmd("zrevrange", key, start, stop)
|
||||||
c.process(cmd)
|
c.process(cmd)
|
||||||
|
|
59
vendor/gopkg.in/redis.v5/internal/pool/conn.go
generated
vendored
59
vendor/gopkg.in/redis.v5/internal/pool/conn.go
generated
vendored
|
@ -2,56 +2,77 @@ package pool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gopkg.in/redis.v5/internal/proto"
|
"gopkg.in/redis.v5/internal/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
const defaultBufSize = 4096
|
|
||||||
|
|
||||||
var noDeadline = time.Time{}
|
var noDeadline = time.Time{}
|
||||||
|
|
||||||
type Conn struct {
|
type Conn struct {
|
||||||
NetConn net.Conn
|
netConn net.Conn
|
||||||
Rd *proto.Reader
|
|
||||||
Wb *proto.WriteBuffer
|
Rd *proto.Reader
|
||||||
|
Wb *proto.WriteBuffer
|
||||||
|
|
||||||
Inited bool
|
Inited bool
|
||||||
UsedAt time.Time
|
usedAt atomic.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConn(netConn net.Conn) *Conn {
|
func NewConn(netConn net.Conn) *Conn {
|
||||||
cn := &Conn{
|
cn := &Conn{
|
||||||
NetConn: netConn,
|
netConn: netConn,
|
||||||
Wb: proto.NewWriteBuffer(),
|
Wb: proto.NewWriteBuffer(),
|
||||||
|
|
||||||
UsedAt: time.Now(),
|
|
||||||
}
|
}
|
||||||
cn.Rd = proto.NewReader(cn.NetConn)
|
cn.Rd = proto.NewReader(cn.netConn)
|
||||||
|
cn.SetUsedAt(time.Now())
|
||||||
return cn
|
return cn
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cn *Conn) UsedAt() time.Time {
|
||||||
|
return cn.usedAt.Load().(time.Time)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cn *Conn) SetUsedAt(tm time.Time) {
|
||||||
|
cn.usedAt.Store(tm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cn *Conn) SetNetConn(netConn net.Conn) {
|
||||||
|
cn.netConn = netConn
|
||||||
|
cn.Rd.Reset(netConn)
|
||||||
|
}
|
||||||
|
|
||||||
func (cn *Conn) IsStale(timeout time.Duration) bool {
|
func (cn *Conn) IsStale(timeout time.Duration) bool {
|
||||||
return timeout > 0 && time.Since(cn.UsedAt) > timeout
|
return timeout > 0 && time.Since(cn.UsedAt()) > timeout
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cn *Conn) SetReadTimeout(timeout time.Duration) error {
|
func (cn *Conn) SetReadTimeout(timeout time.Duration) error {
|
||||||
cn.UsedAt = time.Now()
|
now := time.Now()
|
||||||
|
cn.SetUsedAt(now)
|
||||||
if timeout > 0 {
|
if timeout > 0 {
|
||||||
return cn.NetConn.SetReadDeadline(cn.UsedAt.Add(timeout))
|
return cn.netConn.SetReadDeadline(now.Add(timeout))
|
||||||
}
|
}
|
||||||
return cn.NetConn.SetReadDeadline(noDeadline)
|
return cn.netConn.SetReadDeadline(noDeadline)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cn *Conn) SetWriteTimeout(timeout time.Duration) error {
|
func (cn *Conn) SetWriteTimeout(timeout time.Duration) error {
|
||||||
cn.UsedAt = time.Now()
|
now := time.Now()
|
||||||
|
cn.SetUsedAt(now)
|
||||||
if timeout > 0 {
|
if timeout > 0 {
|
||||||
return cn.NetConn.SetWriteDeadline(cn.UsedAt.Add(timeout))
|
return cn.netConn.SetWriteDeadline(now.Add(timeout))
|
||||||
}
|
}
|
||||||
return cn.NetConn.SetWriteDeadline(noDeadline)
|
return cn.netConn.SetWriteDeadline(noDeadline)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cn *Conn) Write(b []byte) (int, error) {
|
||||||
|
return cn.netConn.Write(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cn *Conn) RemoteAddr() net.Addr {
|
||||||
|
return cn.netConn.RemoteAddr()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cn *Conn) Close() error {
|
func (cn *Conn) Close() error {
|
||||||
return cn.NetConn.Close()
|
return cn.netConn.Close()
|
||||||
}
|
}
|
||||||
|
|
25
vendor/gopkg.in/redis.v5/internal/pool/pool.go
generated
vendored
25
vendor/gopkg.in/redis.v5/internal/pool/pool.go
generated
vendored
|
@ -19,7 +19,9 @@ var (
|
||||||
|
|
||||||
var timers = sync.Pool{
|
var timers = sync.Pool{
|
||||||
New: func() interface{} {
|
New: func() interface{} {
|
||||||
return time.NewTimer(0)
|
t := time.NewTimer(time.Hour)
|
||||||
|
t.Stop()
|
||||||
|
return t
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +43,6 @@ type Pooler interface {
|
||||||
FreeLen() int
|
FreeLen() int
|
||||||
Stats() *Stats
|
Stats() *Stats
|
||||||
Close() error
|
Close() error
|
||||||
Closed() bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type dialer func() (net.Conn, error)
|
type dialer func() (net.Conn, error)
|
||||||
|
@ -96,12 +97,13 @@ func (p *ConnPool) NewConn() (*Conn, error) {
|
||||||
|
|
||||||
func (p *ConnPool) PopFree() *Conn {
|
func (p *ConnPool) PopFree() *Conn {
|
||||||
timer := timers.Get().(*time.Timer)
|
timer := timers.Get().(*time.Timer)
|
||||||
if !timer.Reset(p.poolTimeout) {
|
timer.Reset(p.poolTimeout)
|
||||||
<-timer.C
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case p.queue <- struct{}{}:
|
case p.queue <- struct{}{}:
|
||||||
|
if !timer.Stop() {
|
||||||
|
<-timer.C
|
||||||
|
}
|
||||||
timers.Put(timer)
|
timers.Put(timer)
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
timers.Put(timer)
|
timers.Put(timer)
|
||||||
|
@ -132,19 +134,20 @@ func (p *ConnPool) popFree() *Conn {
|
||||||
|
|
||||||
// Get returns existed connection from the pool or creates a new one.
|
// Get returns existed connection from the pool or creates a new one.
|
||||||
func (p *ConnPool) Get() (*Conn, bool, error) {
|
func (p *ConnPool) Get() (*Conn, bool, error) {
|
||||||
if p.Closed() {
|
if p.closed() {
|
||||||
return nil, false, ErrClosed
|
return nil, false, ErrClosed
|
||||||
}
|
}
|
||||||
|
|
||||||
atomic.AddUint32(&p.stats.Requests, 1)
|
atomic.AddUint32(&p.stats.Requests, 1)
|
||||||
|
|
||||||
timer := timers.Get().(*time.Timer)
|
timer := timers.Get().(*time.Timer)
|
||||||
if !timer.Reset(p.poolTimeout) {
|
timer.Reset(p.poolTimeout)
|
||||||
<-timer.C
|
|
||||||
}
|
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case p.queue <- struct{}{}:
|
case p.queue <- struct{}{}:
|
||||||
|
if !timer.Stop() {
|
||||||
|
<-timer.C
|
||||||
|
}
|
||||||
timers.Put(timer)
|
timers.Put(timer)
|
||||||
case <-timer.C:
|
case <-timer.C:
|
||||||
timers.Put(timer)
|
timers.Put(timer)
|
||||||
|
@ -241,7 +244,7 @@ func (p *ConnPool) Stats() *Stats {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *ConnPool) Closed() bool {
|
func (p *ConnPool) closed() bool {
|
||||||
return atomic.LoadInt32(&p._closed) == 1
|
return atomic.LoadInt32(&p._closed) == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,7 +321,7 @@ func (p *ConnPool) reaper(frequency time.Duration) {
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
for _ = range ticker.C {
|
for _ = range ticker.C {
|
||||||
if p.Closed() {
|
if p.closed() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
n, err := p.ReapStaleConns()
|
n, err := p.ReapStaleConns()
|
||||||
|
|
8
vendor/gopkg.in/redis.v5/internal/pool/pool_single.go
generated
vendored
8
vendor/gopkg.in/redis.v5/internal/pool/pool_single.go
generated
vendored
|
@ -12,10 +12,6 @@ func NewSingleConnPool(cn *Conn) *SingleConnPool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SingleConnPool) First() *Conn {
|
|
||||||
return p.cn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *SingleConnPool) Get() (*Conn, bool, error) {
|
func (p *SingleConnPool) Get() (*Conn, bool, error) {
|
||||||
return p.cn, false, nil
|
return p.cn, false, nil
|
||||||
}
|
}
|
||||||
|
@ -49,7 +45,3 @@ func (p *SingleConnPool) Stats() *Stats {
|
||||||
func (p *SingleConnPool) Close() error {
|
func (p *SingleConnPool) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *SingleConnPool) Closed() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
54
vendor/gopkg.in/redis.v5/internal/pool/pool_sticky.go
generated
vendored
54
vendor/gopkg.in/redis.v5/internal/pool/pool_sticky.go
generated
vendored
|
@ -11,7 +11,7 @@ type StickyConnPool struct {
|
||||||
|
|
||||||
cn *Conn
|
cn *Conn
|
||||||
closed bool
|
closed bool
|
||||||
mx sync.Mutex
|
mu sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ Pooler = (*StickyConnPool)(nil)
|
var _ Pooler = (*StickyConnPool)(nil)
|
||||||
|
@ -23,16 +23,9 @@ func NewStickyConnPool(pool *ConnPool, reusable bool) *StickyConnPool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *StickyConnPool) First() *Conn {
|
|
||||||
p.mx.Lock()
|
|
||||||
cn := p.cn
|
|
||||||
p.mx.Unlock()
|
|
||||||
return cn
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *StickyConnPool) Get() (*Conn, bool, error) {
|
func (p *StickyConnPool) Get() (*Conn, bool, error) {
|
||||||
defer p.mx.Unlock()
|
p.mu.Lock()
|
||||||
p.mx.Lock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
if p.closed {
|
if p.closed {
|
||||||
return nil, false, ErrClosed
|
return nil, false, ErrClosed
|
||||||
|
@ -56,14 +49,12 @@ func (p *StickyConnPool) putUpstream() (err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *StickyConnPool) Put(cn *Conn) error {
|
func (p *StickyConnPool) Put(cn *Conn) error {
|
||||||
defer p.mx.Unlock()
|
p.mu.Lock()
|
||||||
p.mx.Lock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
if p.closed {
|
if p.closed {
|
||||||
return ErrClosed
|
return ErrClosed
|
||||||
}
|
}
|
||||||
if p.cn != cn {
|
|
||||||
panic("p.cn != cn")
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,23 +65,19 @@ func (p *StickyConnPool) removeUpstream(reason error) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *StickyConnPool) Remove(cn *Conn, reason error) error {
|
func (p *StickyConnPool) Remove(cn *Conn, reason error) error {
|
||||||
defer p.mx.Unlock()
|
p.mu.Lock()
|
||||||
p.mx.Lock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
if p.closed {
|
if p.closed {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if p.cn == nil {
|
|
||||||
panic("p.cn == nil")
|
|
||||||
}
|
|
||||||
if cn != nil && p.cn != cn {
|
|
||||||
panic("p.cn != cn")
|
|
||||||
}
|
|
||||||
return p.removeUpstream(reason)
|
return p.removeUpstream(reason)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *StickyConnPool) Len() int {
|
func (p *StickyConnPool) Len() int {
|
||||||
defer p.mx.Unlock()
|
p.mu.Lock()
|
||||||
p.mx.Lock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
if p.cn == nil {
|
if p.cn == nil {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -98,8 +85,9 @@ func (p *StickyConnPool) Len() int {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *StickyConnPool) FreeLen() int {
|
func (p *StickyConnPool) FreeLen() int {
|
||||||
defer p.mx.Unlock()
|
p.mu.Lock()
|
||||||
p.mx.Lock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
if p.cn == nil {
|
if p.cn == nil {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
@ -111,8 +99,9 @@ func (p *StickyConnPool) Stats() *Stats {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *StickyConnPool) Close() error {
|
func (p *StickyConnPool) Close() error {
|
||||||
defer p.mx.Unlock()
|
p.mu.Lock()
|
||||||
p.mx.Lock()
|
defer p.mu.Unlock()
|
||||||
|
|
||||||
if p.closed {
|
if p.closed {
|
||||||
return ErrClosed
|
return ErrClosed
|
||||||
}
|
}
|
||||||
|
@ -128,10 +117,3 @@ func (p *StickyConnPool) Close() error {
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *StickyConnPool) Closed() bool {
|
|
||||||
p.mx.Lock()
|
|
||||||
closed := p.closed
|
|
||||||
p.mx.Unlock()
|
|
||||||
return closed
|
|
||||||
}
|
|
||||||
|
|
27
vendor/gopkg.in/redis.v5/internal/proto/reader.go
generated
vendored
27
vendor/gopkg.in/redis.v5/internal/proto/reader.go
generated
vendored
|
@ -29,10 +29,14 @@ type Reader struct {
|
||||||
func NewReader(rd io.Reader) *Reader {
|
func NewReader(rd io.Reader) *Reader {
|
||||||
return &Reader{
|
return &Reader{
|
||||||
src: bufio.NewReader(rd),
|
src: bufio.NewReader(rd),
|
||||||
buf: make([]byte, 0, bufferSize),
|
buf: make([]byte, 4096),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Reader) Reset(rd io.Reader) {
|
||||||
|
r.src.Reset(rd)
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Reader) PeekBuffered() []byte {
|
func (p *Reader) PeekBuffered() []byte {
|
||||||
if n := p.src.Buffered(); n != 0 {
|
if n := p.src.Buffered(); n != 0 {
|
||||||
b, _ := p.src.Peek(n)
|
b, _ := p.src.Peek(n)
|
||||||
|
@ -42,7 +46,12 @@ func (p *Reader) PeekBuffered() []byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Reader) ReadN(n int) ([]byte, error) {
|
func (p *Reader) ReadN(n int) ([]byte, error) {
|
||||||
return readN(p.src, p.buf, n)
|
b, err := readN(p.src, p.buf, n)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
p.buf = b
|
||||||
|
return b, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Reader) ReadLine() ([]byte, error) {
|
func (p *Reader) ReadLine() ([]byte, error) {
|
||||||
|
@ -72,11 +81,11 @@ func (p *Reader) ReadReply(m MultiBulkParse) (interface{}, error) {
|
||||||
case ErrorReply:
|
case ErrorReply:
|
||||||
return nil, ParseErrorReply(line)
|
return nil, ParseErrorReply(line)
|
||||||
case StatusReply:
|
case StatusReply:
|
||||||
return parseStatusValue(line)
|
return parseStatusValue(line), nil
|
||||||
case IntReply:
|
case IntReply:
|
||||||
return parseInt(line[1:], 10, 64)
|
return parseInt(line[1:], 10, 64)
|
||||||
case StringReply:
|
case StringReply:
|
||||||
return p.readBytesValue(line)
|
return p.readTmpBytesValue(line)
|
||||||
case ArrayReply:
|
case ArrayReply:
|
||||||
n, err := parseArrayLen(line)
|
n, err := parseArrayLen(line)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -111,9 +120,9 @@ func (p *Reader) ReadTmpBytesReply() ([]byte, error) {
|
||||||
case ErrorReply:
|
case ErrorReply:
|
||||||
return nil, ParseErrorReply(line)
|
return nil, ParseErrorReply(line)
|
||||||
case StringReply:
|
case StringReply:
|
||||||
return p.readBytesValue(line)
|
return p.readTmpBytesValue(line)
|
||||||
case StatusReply:
|
case StatusReply:
|
||||||
return parseStatusValue(line)
|
return parseStatusValue(line), nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("redis: can't parse string reply: %.100q", line)
|
return nil, fmt.Errorf("redis: can't parse string reply: %.100q", line)
|
||||||
}
|
}
|
||||||
|
@ -210,7 +219,7 @@ func (p *Reader) ReadScanReply() ([]string, uint64, error) {
|
||||||
return keys, cursor, err
|
return keys, cursor, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Reader) readBytesValue(line []byte) ([]byte, error) {
|
func (p *Reader) readTmpBytesValue(line []byte) ([]byte, error) {
|
||||||
if isNilReply(line) {
|
if isNilReply(line) {
|
||||||
return nil, internal.Nil
|
return nil, internal.Nil
|
||||||
}
|
}
|
||||||
|
@ -297,8 +306,8 @@ func ParseErrorReply(line []byte) error {
|
||||||
return internal.RedisError(string(line[1:]))
|
return internal.RedisError(string(line[1:]))
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseStatusValue(line []byte) ([]byte, error) {
|
func parseStatusValue(line []byte) []byte {
|
||||||
return line[1:], nil
|
return line[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseArrayLen(line []byte) (int64, error) {
|
func parseArrayLen(line []byte) (int64, error) {
|
||||||
|
|
24
vendor/gopkg.in/redis.v5/internal/proto/scan.go
generated
vendored
24
vendor/gopkg.in/redis.v5/internal/proto/scan.go
generated
vendored
|
@ -3,6 +3,7 @@ package proto
|
||||||
import (
|
import (
|
||||||
"encoding"
|
"encoding"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
"gopkg.in/redis.v5/internal"
|
"gopkg.in/redis.v5/internal"
|
||||||
)
|
)
|
||||||
|
@ -105,3 +106,26 @@ func Scan(b []byte, v interface{}) error {
|
||||||
"redis: can't unmarshal %T (consider implementing BinaryUnmarshaler)", v)
|
"redis: can't unmarshal %T (consider implementing BinaryUnmarshaler)", v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ScanSlice(data []string, slice interface{}) error {
|
||||||
|
v := reflect.ValueOf(slice)
|
||||||
|
if !v.IsValid() {
|
||||||
|
return fmt.Errorf("redis: ScanSlice(nil)")
|
||||||
|
}
|
||||||
|
if v.Kind() != reflect.Ptr {
|
||||||
|
return fmt.Errorf("redis: ScanSlice(non-pointer %T)", slice)
|
||||||
|
}
|
||||||
|
v = v.Elem()
|
||||||
|
if v.Kind() != reflect.Slice {
|
||||||
|
return fmt.Errorf("redis: ScanSlice(non-slice %T)", slice)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, s := range data {
|
||||||
|
elem := internal.SliceNextElem(v)
|
||||||
|
if err := Scan([]byte(s), elem.Addr().Interface()); err != nil {
|
||||||
|
return fmt.Errorf("redis: ScanSlice(index=%d value=%q) failed: %s", i, s, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -8,11 +8,13 @@ import (
|
||||||
|
|
||||||
const bufferSize = 4096
|
const bufferSize = 4096
|
||||||
|
|
||||||
type WriteBuffer struct{ b []byte }
|
type WriteBuffer struct {
|
||||||
|
b []byte
|
||||||
|
}
|
||||||
|
|
||||||
func NewWriteBuffer() *WriteBuffer {
|
func NewWriteBuffer() *WriteBuffer {
|
||||||
return &WriteBuffer{
|
return &WriteBuffer{
|
||||||
b: make([]byte, 0, bufferSize),
|
b: make([]byte, 0, 4096),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
20
vendor/gopkg.in/redis.v5/internal/util.go
generated
vendored
20
vendor/gopkg.in/redis.v5/internal/util.go
generated
vendored
|
@ -1,5 +1,7 @@
|
||||||
package internal
|
package internal
|
||||||
|
|
||||||
|
import "reflect"
|
||||||
|
|
||||||
func ToLower(s string) string {
|
func ToLower(s string) string {
|
||||||
if isLower(s) {
|
if isLower(s) {
|
||||||
return s
|
return s
|
||||||
|
@ -25,3 +27,21 @@ func isLower(s string) bool {
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SliceNextElem(v reflect.Value) reflect.Value {
|
||||||
|
if v.Len() < v.Cap() {
|
||||||
|
v.Set(v.Slice(0, v.Len()+1))
|
||||||
|
return v.Index(v.Len() - 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
elemType := v.Type().Elem()
|
||||||
|
|
||||||
|
if elemType.Kind() == reflect.Ptr {
|
||||||
|
elem := reflect.New(elemType.Elem())
|
||||||
|
v.Set(reflect.Append(v, elem))
|
||||||
|
return elem.Elem()
|
||||||
|
}
|
||||||
|
|
||||||
|
v.Set(reflect.Append(v, reflect.Zero(elemType)))
|
||||||
|
return v.Index(v.Len() - 1)
|
||||||
|
}
|
||||||
|
|
3
vendor/gopkg.in/redis.v5/options.go
generated
vendored
3
vendor/gopkg.in/redis.v5/options.go
generated
vendored
|
@ -3,6 +3,7 @@ package redis
|
||||||
import (
|
import (
|
||||||
"crypto/tls"
|
"crypto/tls"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -151,7 +152,7 @@ func ParseURL(redisURL string) (*Options, error) {
|
||||||
o.DB = 0
|
o.DB = 0
|
||||||
case 1:
|
case 1:
|
||||||
if o.DB, err = strconv.Atoi(f[0]); err != nil {
|
if o.DB, err = strconv.Atoi(f[0]); err != nil {
|
||||||
return nil, errors.New("invalid redis database number: " + err.Error())
|
return nil, fmt.Errorf("invalid redis database number: %q", f[0])
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, errors.New("invalid redis URL path: " + u.Path)
|
return nil, errors.New("invalid redis URL path: " + u.Path)
|
||||||
|
|
2
vendor/gopkg.in/redis.v5/pipeline.go
generated
vendored
2
vendor/gopkg.in/redis.v5/pipeline.go
generated
vendored
|
@ -61,8 +61,8 @@ func (c *Pipeline) discard() error {
|
||||||
// Exec always returns list of commands and error of the first failed
|
// Exec always returns list of commands and error of the first failed
|
||||||
// command if any.
|
// command if any.
|
||||||
func (c *Pipeline) Exec() ([]Cmder, error) {
|
func (c *Pipeline) Exec() ([]Cmder, error) {
|
||||||
defer c.mu.Unlock()
|
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
if c.closed {
|
if c.closed {
|
||||||
return nil, pool.ErrClosed
|
return nil, pool.ErrClosed
|
||||||
|
|
79
vendor/gopkg.in/redis.v5/pubsub.go
generated
vendored
79
vendor/gopkg.in/redis.v5/pubsub.go
generated
vendored
|
@ -3,6 +3,7 @@ package redis
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gopkg.in/redis.v5/internal"
|
"gopkg.in/redis.v5/internal"
|
||||||
|
@ -14,7 +15,9 @@ import (
|
||||||
// multiple goroutines.
|
// multiple goroutines.
|
||||||
type PubSub struct {
|
type PubSub struct {
|
||||||
base baseClient
|
base baseClient
|
||||||
|
cmd *Cmd
|
||||||
|
|
||||||
|
mu sync.Mutex
|
||||||
channels []string
|
channels []string
|
||||||
patterns []string
|
patterns []string
|
||||||
}
|
}
|
||||||
|
@ -95,10 +98,10 @@ func (c *PubSub) Close() error {
|
||||||
return c.base.Close()
|
return c.base.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PubSub) Ping(payload string) error {
|
func (c *PubSub) Ping(payload ...string) error {
|
||||||
args := []interface{}{"PING"}
|
args := []interface{}{"PING"}
|
||||||
if payload != "" {
|
if len(payload) == 1 {
|
||||||
args = append(args, payload)
|
args = append(args, payload[0])
|
||||||
}
|
}
|
||||||
cmd := NewCmd(args...)
|
cmd := NewCmd(args...)
|
||||||
|
|
||||||
|
@ -150,31 +153,40 @@ func (p *Pong) String() string {
|
||||||
return "Pong"
|
return "Pong"
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PubSub) newMessage(reply []interface{}) (interface{}, error) {
|
func (c *PubSub) newMessage(reply interface{}) (interface{}, error) {
|
||||||
switch kind := reply[0].(string); kind {
|
switch reply := reply.(type) {
|
||||||
case "subscribe", "unsubscribe", "psubscribe", "punsubscribe":
|
case string:
|
||||||
return &Subscription{
|
|
||||||
Kind: kind,
|
|
||||||
Channel: reply[1].(string),
|
|
||||||
Count: int(reply[2].(int64)),
|
|
||||||
}, nil
|
|
||||||
case "message":
|
|
||||||
return &Message{
|
|
||||||
Channel: reply[1].(string),
|
|
||||||
Payload: reply[2].(string),
|
|
||||||
}, nil
|
|
||||||
case "pmessage":
|
|
||||||
return &Message{
|
|
||||||
Pattern: reply[1].(string),
|
|
||||||
Channel: reply[2].(string),
|
|
||||||
Payload: reply[3].(string),
|
|
||||||
}, nil
|
|
||||||
case "pong":
|
|
||||||
return &Pong{
|
return &Pong{
|
||||||
Payload: reply[1].(string),
|
Payload: reply,
|
||||||
}, nil
|
}, nil
|
||||||
|
case []interface{}:
|
||||||
|
switch kind := reply[0].(string); kind {
|
||||||
|
case "subscribe", "unsubscribe", "psubscribe", "punsubscribe":
|
||||||
|
return &Subscription{
|
||||||
|
Kind: kind,
|
||||||
|
Channel: reply[1].(string),
|
||||||
|
Count: int(reply[2].(int64)),
|
||||||
|
}, nil
|
||||||
|
case "message":
|
||||||
|
return &Message{
|
||||||
|
Channel: reply[1].(string),
|
||||||
|
Payload: reply[2].(string),
|
||||||
|
}, nil
|
||||||
|
case "pmessage":
|
||||||
|
return &Message{
|
||||||
|
Pattern: reply[1].(string),
|
||||||
|
Channel: reply[2].(string),
|
||||||
|
Payload: reply[3].(string),
|
||||||
|
}, nil
|
||||||
|
case "pong":
|
||||||
|
return &Pong{
|
||||||
|
Payload: reply[1].(string),
|
||||||
|
}, nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("redis: unsupported pubsub message: %q", kind)
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("redis: unsupported pubsub notification: %q", kind)
|
return nil, fmt.Errorf("redis: unsupported pubsub message: %#v", reply)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,7 +194,9 @@ func (c *PubSub) newMessage(reply []interface{}) (interface{}, error) {
|
||||||
// is not received in time. This is low-level API and most clients
|
// is not received in time. This is low-level API and most clients
|
||||||
// should use ReceiveMessage.
|
// should use ReceiveMessage.
|
||||||
func (c *PubSub) ReceiveTimeout(timeout time.Duration) (interface{}, error) {
|
func (c *PubSub) ReceiveTimeout(timeout time.Duration) (interface{}, error) {
|
||||||
cmd := NewSliceCmd()
|
if c.cmd == nil {
|
||||||
|
c.cmd = NewCmd()
|
||||||
|
}
|
||||||
|
|
||||||
cn, _, err := c.conn()
|
cn, _, err := c.conn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -190,13 +204,13 @@ func (c *PubSub) ReceiveTimeout(timeout time.Duration) (interface{}, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
cn.SetReadTimeout(timeout)
|
cn.SetReadTimeout(timeout)
|
||||||
err = cmd.readReply(cn)
|
err = c.cmd.readReply(cn)
|
||||||
c.putConn(cn, err)
|
c.putConn(cn, err)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.newMessage(cmd.Val())
|
return c.newMessage(c.cmd.Val())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive returns a message as a Subscription, Message, Pong or error.
|
// Receive returns a message as a Subscription, Message, Pong or error.
|
||||||
|
@ -225,14 +239,14 @@ func (c *PubSub) receiveMessage(timeout time.Duration) (*Message, error) {
|
||||||
errNum++
|
errNum++
|
||||||
if errNum < 3 {
|
if errNum < 3 {
|
||||||
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
|
||||||
err := c.Ping("")
|
err := c.Ping()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
internal.Logf("PubSub.Ping failed: %s", err)
|
internal.Logf("PubSub.Ping failed: %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 3 consequent errors - connection is bad
|
// 3 consequent errors - connection is broken or
|
||||||
// and/or Redis Server is down.
|
// Redis Server is down.
|
||||||
// Sleep to not exceed max number of open connections.
|
// Sleep to not exceed max number of open connections.
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
}
|
}
|
||||||
|
@ -256,9 +270,6 @@ func (c *PubSub) receiveMessage(timeout time.Duration) (*Message, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PubSub) resubscribe() {
|
func (c *PubSub) resubscribe() {
|
||||||
if c.base.closed() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(c.channels) > 0 {
|
if len(c.channels) > 0 {
|
||||||
if err := c.Subscribe(c.channels...); err != nil {
|
if err := c.Subscribe(c.channels...); err != nil {
|
||||||
internal.Logf("Subscribe failed: %s", err)
|
internal.Logf("Subscribe failed: %s", err)
|
||||||
|
|
19
vendor/gopkg.in/redis.v5/redis.go
generated
vendored
19
vendor/gopkg.in/redis.v5/redis.go
generated
vendored
|
@ -17,14 +17,6 @@ func SetLogger(logger *log.Logger) {
|
||||||
internal.Logger = logger
|
internal.Logger = logger
|
||||||
}
|
}
|
||||||
|
|
||||||
type baseClient struct {
|
|
||||||
connPool pool.Pooler
|
|
||||||
opt *Options
|
|
||||||
|
|
||||||
process func(Cmder) error
|
|
||||||
onClose func() error // hook called when client is closed
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *baseClient) String() string {
|
func (c *baseClient) String() string {
|
||||||
return fmt.Sprintf("Redis<%s db:%d>", c.getAddr(), c.opt.DB)
|
return fmt.Sprintf("Redis<%s db:%d>", c.getAddr(), c.opt.DB)
|
||||||
}
|
}
|
||||||
|
@ -134,10 +126,6 @@ func (c *baseClient) cmdTimeout(cmd Cmder) time.Duration {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *baseClient) closed() bool {
|
|
||||||
return c.connPool.Closed()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close closes the client, releasing any open resources.
|
// Close closes the client, releasing any open resources.
|
||||||
//
|
//
|
||||||
// It is rare to Close a Client, as the Client is meant to be
|
// It is rare to Close a Client, as the Client is meant to be
|
||||||
|
@ -309,6 +297,13 @@ func NewClient(opt *Options) *Client {
|
||||||
return newClient(opt, newConnPool(opt))
|
return newClient(opt, newConnPool(opt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) copy() *Client {
|
||||||
|
c2 := new(Client)
|
||||||
|
*c2 = *c
|
||||||
|
c2.cmdable.process = c2.Process
|
||||||
|
return c2
|
||||||
|
}
|
||||||
|
|
||||||
// PoolStats returns connection pool stats.
|
// PoolStats returns connection pool stats.
|
||||||
func (c *Client) PoolStats() *PoolStats {
|
func (c *Client) PoolStats() *PoolStats {
|
||||||
s := c.connPool.Stats()
|
s := c.connPool.Stats()
|
||||||
|
|
35
vendor/gopkg.in/redis.v5/redis_context.go
generated
vendored
Normal file
35
vendor/gopkg.in/redis.v5/redis_context.go
generated
vendored
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
// +build go1.7
|
||||||
|
|
||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"gopkg.in/redis.v5/internal/pool"
|
||||||
|
)
|
||||||
|
|
||||||
|
type baseClient struct {
|
||||||
|
connPool pool.Pooler
|
||||||
|
opt *Options
|
||||||
|
|
||||||
|
process func(Cmder) error
|
||||||
|
onClose func() error // hook called when client is closed
|
||||||
|
|
||||||
|
ctx context.Context
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) Context() context.Context {
|
||||||
|
if c.ctx != nil {
|
||||||
|
return c.ctx
|
||||||
|
}
|
||||||
|
return context.Background()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) WithContext(ctx context.Context) *Client {
|
||||||
|
if ctx == nil {
|
||||||
|
panic("nil context")
|
||||||
|
}
|
||||||
|
c2 := c.copy()
|
||||||
|
c2.ctx = ctx
|
||||||
|
return c2
|
||||||
|
}
|
15
vendor/gopkg.in/redis.v5/redis_no_context.go
generated
vendored
Normal file
15
vendor/gopkg.in/redis.v5/redis_no_context.go
generated
vendored
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
// +build !go1.7
|
||||||
|
|
||||||
|
package redis
|
||||||
|
|
||||||
|
import (
|
||||||
|
"gopkg.in/redis.v5/internal/pool"
|
||||||
|
)
|
||||||
|
|
||||||
|
type baseClient struct {
|
||||||
|
connPool pool.Pooler
|
||||||
|
opt *Options
|
||||||
|
|
||||||
|
process func(Cmder) error
|
||||||
|
onClose func() error // hook called when client is closed
|
||||||
|
}
|
2
vendor/gopkg.in/redis.v5/ring.go
generated
vendored
2
vendor/gopkg.in/redis.v5/ring.go
generated
vendored
|
@ -328,8 +328,8 @@ func (c *Ring) heartbeat() {
|
||||||
// It is rare to Close a Ring, as the Ring is meant to be long-lived
|
// It is rare to Close a Ring, as the Ring is meant to be long-lived
|
||||||
// and shared between many goroutines.
|
// and shared between many goroutines.
|
||||||
func (c *Ring) Close() error {
|
func (c *Ring) Close() error {
|
||||||
defer c.mu.Unlock()
|
|
||||||
c.mu.Lock()
|
c.mu.Lock()
|
||||||
|
defer c.mu.Unlock()
|
||||||
|
|
||||||
if c.closed {
|
if c.closed {
|
||||||
return nil
|
return nil
|
||||||
|
|
10
vendor/gopkg.in/redis.v5/sentinel.go
generated
vendored
10
vendor/gopkg.in/redis.v5/sentinel.go
generated
vendored
|
@ -162,8 +162,8 @@ func (d *sentinelFailover) Pool() *pool.ConnPool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *sentinelFailover) MasterAddr() (string, error) {
|
func (d *sentinelFailover) MasterAddr() (string, error) {
|
||||||
defer d.mu.Unlock()
|
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
|
defer d.mu.Unlock()
|
||||||
|
|
||||||
// Try last working sentinel.
|
// Try last working sentinel.
|
||||||
if d.sentinel != nil {
|
if d.sentinel != nil {
|
||||||
|
@ -258,7 +258,7 @@ func (d *sentinelFailover) discoverSentinels(sentinel *sentinelClient) {
|
||||||
// closeOldConns closes connections to the old master after failover switch.
|
// closeOldConns closes connections to the old master after failover switch.
|
||||||
func (d *sentinelFailover) closeOldConns(newMaster string) {
|
func (d *sentinelFailover) closeOldConns(newMaster string) {
|
||||||
// Good connections that should be put back to the pool. They
|
// Good connections that should be put back to the pool. They
|
||||||
// can't be put immediately, because pool.First will return them
|
// can't be put immediately, because pool.PopFree will return them
|
||||||
// again on next iteration.
|
// again on next iteration.
|
||||||
cnsToPut := make([]*pool.Conn, 0)
|
cnsToPut := make([]*pool.Conn, 0)
|
||||||
|
|
||||||
|
@ -267,10 +267,10 @@ func (d *sentinelFailover) closeOldConns(newMaster string) {
|
||||||
if cn == nil {
|
if cn == nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if cn.NetConn.RemoteAddr().String() != newMaster {
|
if cn.RemoteAddr().String() != newMaster {
|
||||||
err := fmt.Errorf(
|
err := fmt.Errorf(
|
||||||
"sentinel: closing connection to the old master %s",
|
"sentinel: closing connection to the old master %s",
|
||||||
cn.NetConn.RemoteAddr(),
|
cn.RemoteAddr(),
|
||||||
)
|
)
|
||||||
internal.Logf(err.Error())
|
internal.Logf(err.Error())
|
||||||
d.pool.Remove(cn, err)
|
d.pool.Remove(cn, err)
|
||||||
|
@ -289,8 +289,10 @@ func (d *sentinelFailover) listen(sentinel *sentinelClient) {
|
||||||
for {
|
for {
|
||||||
if pubsub == nil {
|
if pubsub == nil {
|
||||||
pubsub = sentinel.PubSub()
|
pubsub = sentinel.PubSub()
|
||||||
|
|
||||||
if err := pubsub.Subscribe("+switch-master"); err != nil {
|
if err := pubsub.Subscribe("+switch-master"); err != nil {
|
||||||
internal.Logf("sentinel: Subscribe failed: %s", err)
|
internal.Logf("sentinel: Subscribe failed: %s", err)
|
||||||
|
pubsub.Close()
|
||||||
d.resetSentinel()
|
d.resetSentinel()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
2
vendor/gopkg.in/thehowl/go-osuapi.v1/osubool.go
generated
vendored
2
vendor/gopkg.in/thehowl/go-osuapi.v1/osubool.go
generated
vendored
|
@ -9,7 +9,7 @@ type OsuBool bool
|
||||||
|
|
||||||
// UnmarshalJSON converts `"0"` to false and `"1"` to true.
|
// UnmarshalJSON converts `"0"` to false and `"1"` to true.
|
||||||
func (o *OsuBool) UnmarshalJSON(data []byte) error {
|
func (o *OsuBool) UnmarshalJSON(data []byte) error {
|
||||||
if string(data) == `"0"` {
|
if string(data) == `0` {
|
||||||
*o = false
|
*o = false
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
44
vendor/vendor.json
vendored
44
vendor/vendor.json
vendored
|
@ -99,10 +99,10 @@
|
||||||
"revisionTime": "2016-10-10T15:00:23Z"
|
"revisionTime": "2016-10-10T15:00:23Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "kUH66xItMsO3QDibGHCWZHa9B3o=",
|
"checksumSHA1": "9ujFdggUmv6hyAgJ+Bjugh0UZAc=",
|
||||||
"path": "github.com/thehowl/go-osuapi",
|
"path": "github.com/thehowl/go-osuapi",
|
||||||
"revision": "77ef7867f23cd52e80dcf97e62447d3b36b1d26a",
|
"revision": "23480db9e43c9a8080cbb681ceaed855e5fca7f3",
|
||||||
"revisionTime": "2016-10-17T20:25:41Z"
|
"revisionTime": "2017-03-12T09:17:38Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "LTOa3BADhwvT0wFCknPueQALm8I=",
|
"checksumSHA1": "LTOa3BADhwvT0wFCknPueQALm8I=",
|
||||||
|
@ -141,46 +141,46 @@
|
||||||
"revisionTime": "2017-01-10T16:23:43Z"
|
"revisionTime": "2017-01-10T16:23:43Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "4+WlWTIczvywOonXZGH34YdCf6s=",
|
"checksumSHA1": "OU/wHTJqhyQfyRnXMVWx1Ox06kQ=",
|
||||||
"path": "gopkg.in/redis.v5",
|
"path": "gopkg.in/redis.v5",
|
||||||
"revision": "6da05abbaa03e90e5878f0ab711478698609fe96",
|
"revision": "a16aeec10ff407b1e7be6dd35797ccf5426ef0f0",
|
||||||
"revisionTime": "2017-01-13T11:52:40Z"
|
"revisionTime": "2017-03-04T11:38:25Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "MQyhe1N+NO0+uyJiEc6M2WGfb3s=",
|
"checksumSHA1": "efyYmNqK7vcPhXW4KXfwbdA1wr4=",
|
||||||
"path": "gopkg.in/redis.v5/internal",
|
"path": "gopkg.in/redis.v5/internal",
|
||||||
"revision": "6da05abbaa03e90e5878f0ab711478698609fe96",
|
"revision": "a16aeec10ff407b1e7be6dd35797ccf5426ef0f0",
|
||||||
"revisionTime": "2017-01-13T11:52:40Z"
|
"revisionTime": "2017-03-04T11:38:25Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "2Ek4SixeRSKOX3mUiBMs3Aw+Guc=",
|
"checksumSHA1": "2Ek4SixeRSKOX3mUiBMs3Aw+Guc=",
|
||||||
"path": "gopkg.in/redis.v5/internal/consistenthash",
|
"path": "gopkg.in/redis.v5/internal/consistenthash",
|
||||||
"revision": "6da05abbaa03e90e5878f0ab711478698609fe96",
|
"revision": "a16aeec10ff407b1e7be6dd35797ccf5426ef0f0",
|
||||||
"revisionTime": "2017-01-13T11:52:40Z"
|
"revisionTime": "2017-03-04T11:38:25Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "rJYVKcBrwYUGl7nuuusmZGrt8mY=",
|
"checksumSHA1": "rJYVKcBrwYUGl7nuuusmZGrt8mY=",
|
||||||
"path": "gopkg.in/redis.v5/internal/hashtag",
|
"path": "gopkg.in/redis.v5/internal/hashtag",
|
||||||
"revision": "6da05abbaa03e90e5878f0ab711478698609fe96",
|
"revision": "a16aeec10ff407b1e7be6dd35797ccf5426ef0f0",
|
||||||
"revisionTime": "2017-01-13T11:52:40Z"
|
"revisionTime": "2017-03-04T11:38:25Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "yLZQUKNxXzwGlzfXhWC0Mwme2nw=",
|
"checksumSHA1": "zsH5BF9qc31R7eEEVYLsjbIigDQ=",
|
||||||
"path": "gopkg.in/redis.v5/internal/pool",
|
"path": "gopkg.in/redis.v5/internal/pool",
|
||||||
"revision": "6da05abbaa03e90e5878f0ab711478698609fe96",
|
"revision": "a16aeec10ff407b1e7be6dd35797ccf5426ef0f0",
|
||||||
"revisionTime": "2017-01-13T11:52:40Z"
|
"revisionTime": "2017-03-04T11:38:25Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "KoSfO3h/KmlaGphIM4KzBGm65O4=",
|
"checksumSHA1": "EqPdu5g8NhzxQOMCvzbreTQlzVE=",
|
||||||
"path": "gopkg.in/redis.v5/internal/proto",
|
"path": "gopkg.in/redis.v5/internal/proto",
|
||||||
"revision": "6da05abbaa03e90e5878f0ab711478698609fe96",
|
"revision": "a16aeec10ff407b1e7be6dd35797ccf5426ef0f0",
|
||||||
"revisionTime": "2017-01-13T11:52:40Z"
|
"revisionTime": "2017-03-04T11:38:25Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "IVLVpxH6lCjsiVVIl/qf8ftjXbg=",
|
"checksumSHA1": "va1m3wm/nxA5IEC/3r4GQeT/+Ro=",
|
||||||
"path": "gopkg.in/thehowl/go-osuapi.v1",
|
"path": "gopkg.in/thehowl/go-osuapi.v1",
|
||||||
"revision": "77ef7867f23cd52e80dcf97e62447d3b36b1d26a",
|
"revision": "23480db9e43c9a8080cbb681ceaed855e5fca7f3",
|
||||||
"revisionTime": "2016-10-17T20:25:41Z"
|
"revisionTime": "2017-03-12T09:17:38Z"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"checksumSHA1": "SI9tgNMlnMhxP7t6cAGuDjvoAHg=",
|
"checksumSHA1": "SI9tgNMlnMhxP7t6cAGuDjvoAHg=",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user