build(deps): bump github.com/redis/go-redis/v9 from 9.1.0 to 9.2.1 (#7107)

Bumps https://github.com/redis/go-redis from 9.1.0 to 9.2.1.
- Release notes: https://github.com/redis/go-redis/releases/tag/v9.2.1
- Changelog: https://github.com/redis/go-redis/compare/v9.1.0...v9.2.1
This commit is contained in:
dependabot[bot] 2023-10-27 09:12:54 -07:00 committed by GitHub
parent c84201c09a
commit 50ec4786e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 4743 additions and 3505 deletions

2
go.mod
View File

@ -23,7 +23,7 @@ require (
github.com/miekg/pkcs11 v1.1.1
github.com/prometheus/client_golang v1.15.1
github.com/prometheus/client_model v0.4.0
github.com/redis/go-redis/v9 v9.1.0
github.com/redis/go-redis/v9 v9.2.1
github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399
github.com/weppos/publicsuffix-go v0.30.1-0.20230620154423-38c92ad2d5c6
github.com/zmap/zcrypto v0.0.0-20230310154051-c8b263fd8300

12
go.sum
View File

@ -91,10 +91,10 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bsm/ginkgo/v2 v2.9.5 h1:rtVBYPs3+TC5iLUVOis1B9tjLTup7Cj5IfzosKtvTJ0=
github.com/bsm/ginkgo/v2 v2.9.5/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y=
github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
@ -329,8 +329,8 @@ github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7z
github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY=
github.com/redis/go-redis/v9 v9.1.0/go.mod h1:urWj3He21Dj5k4TK1y59xH8Uj6ATueP8AH1cY3lZl4c=
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg=
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=

View File

@ -2,3 +2,5 @@
testdata/*
.idea/
.DS_Store
*.tar.gz
*.dic

101
vendor/github.com/redis/go-redis/v9/CONTRIBUTING.md generated vendored Normal file
View File

@ -0,0 +1,101 @@
# Contributing
## Introduction
We appreciate your interest in considering contributing to go-redis.
Community contributions mean a lot to us.
## Contributions we need
You may already know how you'd like to contribute, whether it's a fix for a bug you
encountered, or a new feature your team wants to use.
If you don't know where to start, consider improving
documentation, bug triaging, and writing tutorials are all examples of
helpful contributions that mean less work for you.
## Your First Contribution
Unsure where to begin contributing? You can start by looking through
[help-wanted
issues](https://github.com/redis/go-redis/issues?q=is%3Aopen+is%3Aissue+label%3ahelp-wanted).
Never contributed to open source before? Here are a couple of friendly
tutorials:
- <http://makeapullrequest.com/>
- <http://www.firsttimersonly.com/>
## Getting Started
Here's how to get started with your code contribution:
1. Create your own fork of go-redis
2. Do the changes in your fork
3. If you need a development environment, run `make test`. Note: this clones and builds the latest release of [redis](https://redis.io). You also need a redis-stack-server docker, in order to run the capabilities tests. This can be started by running:
```docker run -p 6379:6379 -it redis/redis-stack-server:edge```
4. While developing, make sure the tests pass by running `make tests`
5. If you like the change and think the project could use it, send a
pull request
To see what else is part of the automation, run `invoke -l`
## Testing
Call `make test` to run all tests, including linters.
Continuous Integration uses these same wrappers to run all of these
tests against multiple versions of python. Feel free to test your
changes against all the go versions supported, as declared by the
[build.yml](./.github/workflows/build.yml) file.
### Troubleshooting
If you get any errors when running `make test`, make sure
that you are using supported versions of Docker and go.
## How to Report a Bug
### Security Vulnerabilities
**NOTE**: If you find a security vulnerability, do NOT open an issue.
Email [Redis Open Source (<oss@redis.com>)](mailto:oss@redis.com) instead.
In order to determine whether you are dealing with a security issue, ask
yourself these two questions:
- Can I access something that's not mine, or something I shouldn't
have access to?
- Can I disable something for other people?
If the answer to either of those two questions are *yes*, then you're
probably dealing with a security issue. Note that even if you answer
*no* to both questions, you may still be dealing with a security
issue, so if you're unsure, just email [us](mailto:oss@redis.com).
### Everything Else
When filing an issue, make sure to answer these five questions:
1. What version of go-redis are you using?
2. What version of redis are you using?
3. What did you do?
4. What did you expect to see?
5. What did you see instead?
## Suggest a feature or enhancement
If you'd like to contribute a new feature, make sure you check our
issue list to see if someone has already proposed it. Work may already
be underway on the feature you want or we may have rejected a
feature like it already.
If you don't see anything, open a new issue that describes the feature
you would like and how it should work.
## Code review process
The core team regularly looks at pull requests. We will provide
feedback as soon as possible. After receiving our feedback, please respond
within two weeks. After that time, we may close your PR if it isn't
showing any activity.

View File

@ -19,17 +19,20 @@ testdeps: testdata/redis/src/redis-server
bench: testdeps
go test ./... -test.run=NONE -test.bench=. -test.benchmem
.PHONY: all test testdeps bench
.PHONY: all test testdeps bench fmt
build:
go build .
testdata/redis:
mkdir -p $@
wget -qO- https://download.redis.io/releases/redis-7.2-rc3.tar.gz | tar xvz --strip-components=1 -C $@
wget -qO- https://download.redis.io/releases/redis-7.2.1.tar.gz | tar xvz --strip-components=1 -C $@
testdata/redis/src/redis-server: testdata/redis
cd $< && make all
fmt:
gofmt -w -s ./
gofumpt -w ./
goimports -w -local github.com/redis/go-redis ./
go_mod_tidy:

View File

@ -69,8 +69,9 @@ go get github.com/redis/go-redis/v9
```go
import (
"context"
"github.com/redis/go-redis/v9"
"fmt"
"github.com/redis/go-redis/v9"
)
var ctx = context.Background()
@ -125,8 +126,9 @@ go-redis also supports connecting via the [redis uri specification](https://gith
```go
import (
"context"
"github.com/redis/go-redis/v9"
"fmt"
"github.com/redis/go-redis/v9"
)
var ctx = context.Background()
@ -140,6 +142,10 @@ func ExampleClient() {
rdb := redis.NewClient(opts)
```
## Contributing
Please see [out contributing guidelines](CONTRIBUTING.md) to help us improve this library!
## Look and feel
Some corner cases:

35
vendor/github.com/redis/go-redis/v9/acl_commands.go generated vendored Normal file
View File

@ -0,0 +1,35 @@
package redis
import "context"
type ACLCmdable interface {
ACLDryRun(ctx context.Context, username string, command ...interface{}) *StringCmd
ACLLog(ctx context.Context, count int64) *ACLLogCmd
ACLLogReset(ctx context.Context) *StatusCmd
}
func (c cmdable) ACLDryRun(ctx context.Context, username string, command ...interface{}) *StringCmd {
args := make([]interface{}, 0, 3+len(command))
args = append(args, "acl", "dryrun", username)
args = append(args, command...)
cmd := NewStringCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ACLLog(ctx context.Context, count int64) *ACLLogCmd {
args := make([]interface{}, 0, 3)
args = append(args, "acl", "log")
if count > 0 {
args = append(args, count)
}
cmd := NewACLLogCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ACLLogReset(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "acl", "log", "reset")
_ = c(ctx, cmd)
return cmd
}

129
vendor/github.com/redis/go-redis/v9/bitmap_commands.go generated vendored Normal file
View File

@ -0,0 +1,129 @@
package redis
import "context"
type BitMapCmdable interface {
GetBit(ctx context.Context, key string, offset int64) *IntCmd
SetBit(ctx context.Context, key string, offset int64, value int) *IntCmd
BitCount(ctx context.Context, key string, bitCount *BitCount) *IntCmd
BitOpAnd(ctx context.Context, destKey string, keys ...string) *IntCmd
BitOpOr(ctx context.Context, destKey string, keys ...string) *IntCmd
BitOpXor(ctx context.Context, destKey string, keys ...string) *IntCmd
BitOpNot(ctx context.Context, destKey string, key string) *IntCmd
BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd
BitPosSpan(ctx context.Context, key string, bit int8, start, end int64, span string) *IntCmd
BitField(ctx context.Context, key string, values ...interface{}) *IntSliceCmd
}
func (c cmdable) GetBit(ctx context.Context, key string, offset int64) *IntCmd {
cmd := NewIntCmd(ctx, "getbit", key, offset)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SetBit(ctx context.Context, key string, offset int64, value int) *IntCmd {
cmd := NewIntCmd(
ctx,
"setbit",
key,
offset,
value,
)
_ = c(ctx, cmd)
return cmd
}
type BitCount struct {
Start, End int64
}
func (c cmdable) BitCount(ctx context.Context, key string, bitCount *BitCount) *IntCmd {
args := []interface{}{"bitcount", key}
if bitCount != nil {
args = append(
args,
bitCount.Start,
bitCount.End,
)
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) bitOp(ctx context.Context, op, destKey string, keys ...string) *IntCmd {
args := make([]interface{}, 3+len(keys))
args[0] = "bitop"
args[1] = op
args[2] = destKey
for i, key := range keys {
args[3+i] = key
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) BitOpAnd(ctx context.Context, destKey string, keys ...string) *IntCmd {
return c.bitOp(ctx, "and", destKey, keys...)
}
func (c cmdable) BitOpOr(ctx context.Context, destKey string, keys ...string) *IntCmd {
return c.bitOp(ctx, "or", destKey, keys...)
}
func (c cmdable) BitOpXor(ctx context.Context, destKey string, keys ...string) *IntCmd {
return c.bitOp(ctx, "xor", destKey, keys...)
}
func (c cmdable) BitOpNot(ctx context.Context, destKey string, key string) *IntCmd {
return c.bitOp(ctx, "not", destKey, key)
}
// BitPos is an API before Redis version 7.0, cmd: bitpos key bit start end
// if you need the `byte | bit` parameter, please use `BitPosSpan`.
func (c cmdable) BitPos(ctx context.Context, key string, bit int64, pos ...int64) *IntCmd {
args := make([]interface{}, 3+len(pos))
args[0] = "bitpos"
args[1] = key
args[2] = bit
switch len(pos) {
case 0:
case 1:
args[3] = pos[0]
case 2:
args[3] = pos[0]
args[4] = pos[1]
default:
panic("too many arguments")
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// BitPosSpan supports the `byte | bit` parameters in redis version 7.0,
// the bitpos command defaults to using byte type for the `start-end` range,
// which means it counts in bytes from start to end. you can set the value
// of "span" to determine the type of `start-end`.
// span = "bit", cmd: bitpos key bit start end bit
// span = "byte", cmd: bitpos key bit start end byte
func (c cmdable) BitPosSpan(ctx context.Context, key string, bit int8, start, end int64, span string) *IntCmd {
cmd := NewIntCmd(ctx, "bitpos", key, bit, start, end, span)
_ = c(ctx, cmd)
return cmd
}
// BitField accepts multiple values:
// - BitField("set", "i1", "offset1", "value1","cmd2", "type2", "offset2", "value2")
// - BitField([]string{"cmd1", "type1", "offset1", "value1","cmd2", "type2", "offset2", "value2"})
// - BitField([]interface{}{"cmd1", "type1", "offset1", "value1","cmd2", "type2", "offset2", "value2"})
func (c cmdable) BitField(ctx context.Context, key string, values ...interface{}) *IntSliceCmd {
args := make([]interface{}, 2, 2+len(values))
args[0] = "bitfield"
args[1] = key
args = appendArgs(args, values)
cmd := NewIntSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}

View File

@ -1,109 +1,192 @@
package redis
import (
"context"
"sync"
"sync/atomic"
)
import "context"
func (c *ClusterClient) DBSize(ctx context.Context) *IntCmd {
cmd := NewIntCmd(ctx, "dbsize")
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
var size int64
err := c.ForEachMaster(ctx, func(ctx context.Context, master *Client) error {
n, err := master.DBSize(ctx).Result()
if err != nil {
return err
}
atomic.AddInt64(&size, n)
return nil
})
if err != nil {
cmd.SetErr(err)
} else {
cmd.val = size
}
return nil
})
type ClusterCmdable interface {
ClusterMyShardID(ctx context.Context) *StringCmd
ClusterSlots(ctx context.Context) *ClusterSlotsCmd
ClusterShards(ctx context.Context) *ClusterShardsCmd
ClusterLinks(ctx context.Context) *ClusterLinksCmd
ClusterNodes(ctx context.Context) *StringCmd
ClusterMeet(ctx context.Context, host, port string) *StatusCmd
ClusterForget(ctx context.Context, nodeID string) *StatusCmd
ClusterReplicate(ctx context.Context, nodeID string) *StatusCmd
ClusterResetSoft(ctx context.Context) *StatusCmd
ClusterResetHard(ctx context.Context) *StatusCmd
ClusterInfo(ctx context.Context) *StringCmd
ClusterKeySlot(ctx context.Context, key string) *IntCmd
ClusterGetKeysInSlot(ctx context.Context, slot int, count int) *StringSliceCmd
ClusterCountFailureReports(ctx context.Context, nodeID string) *IntCmd
ClusterCountKeysInSlot(ctx context.Context, slot int) *IntCmd
ClusterDelSlots(ctx context.Context, slots ...int) *StatusCmd
ClusterDelSlotsRange(ctx context.Context, min, max int) *StatusCmd
ClusterSaveConfig(ctx context.Context) *StatusCmd
ClusterSlaves(ctx context.Context, nodeID string) *StringSliceCmd
ClusterFailover(ctx context.Context) *StatusCmd
ClusterAddSlots(ctx context.Context, slots ...int) *StatusCmd
ClusterAddSlotsRange(ctx context.Context, min, max int) *StatusCmd
ReadOnly(ctx context.Context) *StatusCmd
ReadWrite(ctx context.Context) *StatusCmd
}
func (c cmdable) ClusterMyShardID(ctx context.Context) *StringCmd {
cmd := NewStringCmd(ctx, "cluster", "myshardid")
_ = c(ctx, cmd)
return cmd
}
func (c *ClusterClient) ScriptLoad(ctx context.Context, script string) *StringCmd {
cmd := NewStringCmd(ctx, "script", "load", script)
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
var mu sync.Mutex
err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error {
val, err := shard.ScriptLoad(ctx, script).Result()
if err != nil {
return err
}
mu.Lock()
if cmd.Val() == "" {
cmd.val = val
}
mu.Unlock()
return nil
})
if err != nil {
cmd.SetErr(err)
}
return nil
})
func (c cmdable) ClusterSlots(ctx context.Context) *ClusterSlotsCmd {
cmd := NewClusterSlotsCmd(ctx, "cluster", "slots")
_ = c(ctx, cmd)
return cmd
}
func (c *ClusterClient) ScriptFlush(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "script", "flush")
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error {
return shard.ScriptFlush(ctx).Err()
})
if err != nil {
cmd.SetErr(err)
}
return nil
})
func (c cmdable) ClusterShards(ctx context.Context) *ClusterShardsCmd {
cmd := NewClusterShardsCmd(ctx, "cluster", "shards")
_ = c(ctx, cmd)
return cmd
}
func (c *ClusterClient) ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd {
args := make([]interface{}, 2+len(hashes))
args[0] = "script"
args[1] = "exists"
for i, hash := range hashes {
args[2+i] = hash
func (c cmdable) ClusterLinks(ctx context.Context) *ClusterLinksCmd {
cmd := NewClusterLinksCmd(ctx, "cluster", "links")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterNodes(ctx context.Context) *StringCmd {
cmd := NewStringCmd(ctx, "cluster", "nodes")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterMeet(ctx context.Context, host, port string) *StatusCmd {
cmd := NewStatusCmd(ctx, "cluster", "meet", host, port)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterForget(ctx context.Context, nodeID string) *StatusCmd {
cmd := NewStatusCmd(ctx, "cluster", "forget", nodeID)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterReplicate(ctx context.Context, nodeID string) *StatusCmd {
cmd := NewStatusCmd(ctx, "cluster", "replicate", nodeID)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterResetSoft(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "cluster", "reset", "soft")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterResetHard(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "cluster", "reset", "hard")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterInfo(ctx context.Context) *StringCmd {
cmd := NewStringCmd(ctx, "cluster", "info")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterKeySlot(ctx context.Context, key string) *IntCmd {
cmd := NewIntCmd(ctx, "cluster", "keyslot", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterGetKeysInSlot(ctx context.Context, slot int, count int) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "cluster", "getkeysinslot", slot, count)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterCountFailureReports(ctx context.Context, nodeID string) *IntCmd {
cmd := NewIntCmd(ctx, "cluster", "count-failure-reports", nodeID)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterCountKeysInSlot(ctx context.Context, slot int) *IntCmd {
cmd := NewIntCmd(ctx, "cluster", "countkeysinslot", slot)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterDelSlots(ctx context.Context, slots ...int) *StatusCmd {
args := make([]interface{}, 2+len(slots))
args[0] = "cluster"
args[1] = "delslots"
for i, slot := range slots {
args[2+i] = slot
}
cmd := NewBoolSliceCmd(ctx, args...)
result := make([]bool, len(hashes))
for i := range result {
result[i] = true
}
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
var mu sync.Mutex
err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error {
val, err := shard.ScriptExists(ctx, hashes...).Result()
if err != nil {
return err
}
mu.Lock()
for i, v := range val {
result[i] = result[i] && v
}
mu.Unlock()
return nil
})
if err != nil {
cmd.SetErr(err)
} else {
cmd.val = result
}
return nil
})
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterDelSlotsRange(ctx context.Context, min, max int) *StatusCmd {
size := max - min + 1
slots := make([]int, size)
for i := 0; i < size; i++ {
slots[i] = min + i
}
return c.ClusterDelSlots(ctx, slots...)
}
func (c cmdable) ClusterSaveConfig(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "cluster", "saveconfig")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterSlaves(ctx context.Context, nodeID string) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "cluster", "slaves", nodeID)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterFailover(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "cluster", "failover")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterAddSlots(ctx context.Context, slots ...int) *StatusCmd {
args := make([]interface{}, 2+len(slots))
args[0] = "cluster"
args[1] = "addslots"
for i, num := range slots {
args[2+i] = num
}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ClusterAddSlotsRange(ctx context.Context, min, max int) *StatusCmd {
size := max - min + 1
slots := make([]int, size)
for i := 0; i < size; i++ {
slots[i] = min + i
}
return c.ClusterAddSlots(ctx, slots...)
}
func (c cmdable) ReadOnly(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "readonly")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ReadWrite(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "readwrite")
_ = c(ctx, cmd)
return cmd
}

View File

@ -1351,6 +1351,65 @@ func (cmd *MapStringIntCmd) readReply(rd *proto.Reader) error {
return nil
}
// ------------------------------------------------------------------------------
type MapStringSliceInterfaceCmd struct {
baseCmd
val map[string][]interface{}
}
func NewMapStringSliceInterfaceCmd(ctx context.Context, args ...interface{}) *MapStringSliceInterfaceCmd {
return &MapStringSliceInterfaceCmd{
baseCmd: baseCmd{
ctx: ctx,
args: args,
},
}
}
func (cmd *MapStringSliceInterfaceCmd) String() string {
return cmdString(cmd, cmd.val)
}
func (cmd *MapStringSliceInterfaceCmd) SetVal(val map[string][]interface{}) {
cmd.val = val
}
func (cmd *MapStringSliceInterfaceCmd) Result() (map[string][]interface{}, error) {
return cmd.val, cmd.err
}
func (cmd *MapStringSliceInterfaceCmd) Val() map[string][]interface{} {
return cmd.val
}
func (cmd *MapStringSliceInterfaceCmd) readReply(rd *proto.Reader) (err error) {
n, err := rd.ReadMapLen()
if err != nil {
return err
}
cmd.val = make(map[string][]interface{}, n)
for i := 0; i < n; i++ {
k, err := rd.ReadString()
if err != nil {
return err
}
nn, err := rd.ReadArrayLen()
if err != nil {
return err
}
cmd.val[k] = make([]interface{}, nn)
for j := 0; j < nn; j++ {
value, err := rd.ReadReply()
if err != nil {
return err
}
cmd.val[k][j] = value
}
}
return nil
}
//------------------------------------------------------------------------------
type StringStructMapCmd struct {
@ -4265,7 +4324,6 @@ func (cmd *FunctionStatsCmd) readDuration(rd *proto.Reader) (time.Duration, erro
}
func (cmd *FunctionStatsCmd) readCommand(rd *proto.Reader) ([]string, error) {
n, err := rd.ReadArrayLen()
if err != nil {
return nil, err
@ -4282,6 +4340,7 @@ func (cmd *FunctionStatsCmd) readCommand(rd *proto.Reader) ([]string, error) {
return command, nil
}
func (cmd *FunctionStatsCmd) readRunningScripts(rd *proto.Reader) ([]RunningScript, bool, error) {
n, err := rd.ReadArrayLen()
if err != nil {
@ -5233,3 +5292,9 @@ func (cmd *ACLLogCmd) readReply(rd *proto.Reader) error {
return nil
}
// LibraryInfo holds the library info.
type LibraryInfo struct {
LibName *string
LibVer *string
}

File diff suppressed because it is too large Load Diff

View File

@ -6,7 +6,7 @@ import (
"strings"
)
type gearsCmdable interface {
type GearsCmdable interface {
TFunctionLoad(ctx context.Context, lib string) *StatusCmd
TFunctionLoadArgs(ctx context.Context, lib string, options *TFunctionLoadOptions) *StatusCmd
TFunctionDelete(ctx context.Context, libName string) *StatusCmd
@ -17,6 +17,7 @@ type gearsCmdable interface {
TFCallASYNC(ctx context.Context, libName string, funcName string, numKeys int) *Cmd
TFCallASYNCArgs(ctx context.Context, libName string, funcName string, numKeys int, options *TFCallOptions) *Cmd
}
type TFunctionLoadOptions struct {
Replace bool
Config string
@ -88,7 +89,6 @@ func (c cmdable) TFunctionListArgs(ctx context.Context, options *TFunctionListOp
}
if options.Library != "" {
args = append(args, "LIBRARY", options.Library)
}
}
cmd := NewMapStringInterfaceSliceCmd(ctx, args...)
@ -110,17 +110,11 @@ func (c cmdable) TFCallArgs(ctx context.Context, libName string, funcName string
lf := libName + "." + funcName
args := []interface{}{"TFCALL", lf, numKeys}
if options != nil {
if options.Keys != nil {
for _, key := range options.Keys {
args = append(args, key)
}
for _, key := range options.Keys {
args = append(args, key)
}
if options.Arguments != nil {
for _, key := range options.Arguments {
args = append(args, key)
}
for _, key := range options.Arguments {
args = append(args, key)
}
}
cmd := NewCmd(ctx, args...)
@ -142,17 +136,11 @@ func (c cmdable) TFCallASYNCArgs(ctx context.Context, libName string, funcName s
lf := fmt.Sprintf("%s.%s", libName, funcName)
args := []interface{}{"TFCALLASYNC", lf, numKeys}
if options != nil {
if options.Keys != nil {
for _, key := range options.Keys {
args = append(args, key)
}
for _, key := range options.Keys {
args = append(args, key)
}
if options.Arguments != nil {
for _, key := range options.Arguments {
args = append(args, key)
}
for _, key := range options.Arguments {
args = append(args, key)
}
}
cmd := NewCmd(ctx, args...)

377
vendor/github.com/redis/go-redis/v9/generic_commands.go generated vendored Normal file
View File

@ -0,0 +1,377 @@
package redis
import (
"context"
"time"
)
type GenericCmdable interface {
Del(ctx context.Context, keys ...string) *IntCmd
Dump(ctx context.Context, key string) *StringCmd
Exists(ctx context.Context, keys ...string) *IntCmd
Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd
ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd
ExpireTime(ctx context.Context, key string) *DurationCmd
ExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd
ExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd
ExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd
ExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd
Keys(ctx context.Context, pattern string) *StringSliceCmd
Migrate(ctx context.Context, host, port, key string, db int, timeout time.Duration) *StatusCmd
Move(ctx context.Context, key string, db int) *BoolCmd
ObjectRefCount(ctx context.Context, key string) *IntCmd
ObjectEncoding(ctx context.Context, key string) *StringCmd
ObjectIdleTime(ctx context.Context, key string) *DurationCmd
Persist(ctx context.Context, key string) *BoolCmd
PExpire(ctx context.Context, key string, expiration time.Duration) *BoolCmd
PExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd
PExpireTime(ctx context.Context, key string) *DurationCmd
PTTL(ctx context.Context, key string) *DurationCmd
RandomKey(ctx context.Context) *StringCmd
Rename(ctx context.Context, key, newkey string) *StatusCmd
RenameNX(ctx context.Context, key, newkey string) *BoolCmd
Restore(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd
RestoreReplace(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd
Sort(ctx context.Context, key string, sort *Sort) *StringSliceCmd
SortRO(ctx context.Context, key string, sort *Sort) *StringSliceCmd
SortStore(ctx context.Context, key, store string, sort *Sort) *IntCmd
SortInterfaces(ctx context.Context, key string, sort *Sort) *SliceCmd
Touch(ctx context.Context, keys ...string) *IntCmd
TTL(ctx context.Context, key string) *DurationCmd
Type(ctx context.Context, key string) *StatusCmd
Copy(ctx context.Context, sourceKey string, destKey string, db int, replace bool) *IntCmd
Scan(ctx context.Context, cursor uint64, match string, count int64) *ScanCmd
ScanType(ctx context.Context, cursor uint64, match string, count int64, keyType string) *ScanCmd
}
func (c cmdable) Del(ctx context.Context, keys ...string) *IntCmd {
args := make([]interface{}, 1+len(keys))
args[0] = "del"
for i, key := range keys {
args[1+i] = key
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Unlink(ctx context.Context, keys ...string) *IntCmd {
args := make([]interface{}, 1+len(keys))
args[0] = "unlink"
for i, key := range keys {
args[1+i] = key
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Dump(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "dump", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Exists(ctx context.Context, keys ...string) *IntCmd {
args := make([]interface{}, 1+len(keys))
args[0] = "exists"
for i, key := range keys {
args[1+i] = key
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Expire(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
return c.expire(ctx, key, expiration, "")
}
func (c cmdable) ExpireNX(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
return c.expire(ctx, key, expiration, "NX")
}
func (c cmdable) ExpireXX(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
return c.expire(ctx, key, expiration, "XX")
}
func (c cmdable) ExpireGT(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
return c.expire(ctx, key, expiration, "GT")
}
func (c cmdable) ExpireLT(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
return c.expire(ctx, key, expiration, "LT")
}
func (c cmdable) expire(
ctx context.Context, key string, expiration time.Duration, mode string,
) *BoolCmd {
args := make([]interface{}, 3, 4)
args[0] = "expire"
args[1] = key
args[2] = formatSec(ctx, expiration)
if mode != "" {
args = append(args, mode)
}
cmd := NewBoolCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd {
cmd := NewBoolCmd(ctx, "expireat", key, tm.Unix())
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ExpireTime(ctx context.Context, key string) *DurationCmd {
cmd := NewDurationCmd(ctx, time.Second, "expiretime", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Keys(ctx context.Context, pattern string) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "keys", pattern)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Migrate(ctx context.Context, host, port, key string, db int, timeout time.Duration) *StatusCmd {
cmd := NewStatusCmd(
ctx,
"migrate",
host,
port,
key,
db,
formatMs(ctx, timeout),
)
cmd.setReadTimeout(timeout)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Move(ctx context.Context, key string, db int) *BoolCmd {
cmd := NewBoolCmd(ctx, "move", key, db)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ObjectRefCount(ctx context.Context, key string) *IntCmd {
cmd := NewIntCmd(ctx, "object", "refcount", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ObjectEncoding(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "object", "encoding", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ObjectIdleTime(ctx context.Context, key string) *DurationCmd {
cmd := NewDurationCmd(ctx, time.Second, "object", "idletime", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Persist(ctx context.Context, key string) *BoolCmd {
cmd := NewBoolCmd(ctx, "persist", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PExpire(ctx context.Context, key string, expiration time.Duration) *BoolCmd {
cmd := NewBoolCmd(ctx, "pexpire", key, formatMs(ctx, expiration))
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PExpireAt(ctx context.Context, key string, tm time.Time) *BoolCmd {
cmd := NewBoolCmd(
ctx,
"pexpireat",
key,
tm.UnixNano()/int64(time.Millisecond),
)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PExpireTime(ctx context.Context, key string) *DurationCmd {
cmd := NewDurationCmd(ctx, time.Millisecond, "pexpiretime", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PTTL(ctx context.Context, key string) *DurationCmd {
cmd := NewDurationCmd(ctx, time.Millisecond, "pttl", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) RandomKey(ctx context.Context) *StringCmd {
cmd := NewStringCmd(ctx, "randomkey")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Rename(ctx context.Context, key, newkey string) *StatusCmd {
cmd := NewStatusCmd(ctx, "rename", key, newkey)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) RenameNX(ctx context.Context, key, newkey string) *BoolCmd {
cmd := NewBoolCmd(ctx, "renamenx", key, newkey)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Restore(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd {
cmd := NewStatusCmd(
ctx,
"restore",
key,
formatMs(ctx, ttl),
value,
)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) RestoreReplace(ctx context.Context, key string, ttl time.Duration, value string) *StatusCmd {
cmd := NewStatusCmd(
ctx,
"restore",
key,
formatMs(ctx, ttl),
value,
"replace",
)
_ = c(ctx, cmd)
return cmd
}
type Sort struct {
By string
Offset, Count int64
Get []string
Order string
Alpha bool
}
func (sort *Sort) args(command, key string) []interface{} {
args := []interface{}{command, key}
if sort.By != "" {
args = append(args, "by", sort.By)
}
if sort.Offset != 0 || sort.Count != 0 {
args = append(args, "limit", sort.Offset, sort.Count)
}
for _, get := range sort.Get {
args = append(args, "get", get)
}
if sort.Order != "" {
args = append(args, sort.Order)
}
if sort.Alpha {
args = append(args, "alpha")
}
return args
}
func (c cmdable) SortRO(ctx context.Context, key string, sort *Sort) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, sort.args("sort_ro", key)...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Sort(ctx context.Context, key string, sort *Sort) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, sort.args("sort", key)...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SortStore(ctx context.Context, key, store string, sort *Sort) *IntCmd {
args := sort.args("sort", key)
if store != "" {
args = append(args, "store", store)
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SortInterfaces(ctx context.Context, key string, sort *Sort) *SliceCmd {
cmd := NewSliceCmd(ctx, sort.args("sort", key)...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Touch(ctx context.Context, keys ...string) *IntCmd {
args := make([]interface{}, len(keys)+1)
args[0] = "touch"
for i, key := range keys {
args[i+1] = key
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) TTL(ctx context.Context, key string) *DurationCmd {
cmd := NewDurationCmd(ctx, time.Second, "ttl", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Type(ctx context.Context, key string) *StatusCmd {
cmd := NewStatusCmd(ctx, "type", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Copy(ctx context.Context, sourceKey, destKey string, db int, replace bool) *IntCmd {
args := []interface{}{"copy", sourceKey, destKey, "DB", db}
if replace {
args = append(args, "REPLACE")
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
//------------------------------------------------------------------------------
func (c cmdable) Scan(ctx context.Context, cursor uint64, match string, count int64) *ScanCmd {
args := []interface{}{"scan", cursor}
if match != "" {
args = append(args, "match", match)
}
if count > 0 {
args = append(args, "count", count)
}
cmd := NewScanCmd(ctx, c, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ScanType(ctx context.Context, cursor uint64, match string, count int64, keyType string) *ScanCmd {
args := []interface{}{"scan", cursor}
if match != "" {
args = append(args, "match", match)
}
if count > 0 {
args = append(args, "count", count)
}
if keyType != "" {
args = append(args, "type", keyType)
}
cmd := NewScanCmd(ctx, c, args...)
_ = c(ctx, cmd)
return cmd
}

155
vendor/github.com/redis/go-redis/v9/geo_commands.go generated vendored Normal file
View File

@ -0,0 +1,155 @@
package redis
import (
"context"
"errors"
)
type GeoCmdable interface {
GeoAdd(ctx context.Context, key string, geoLocation ...*GeoLocation) *IntCmd
GeoPos(ctx context.Context, key string, members ...string) *GeoPosCmd
GeoRadius(ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery) *GeoLocationCmd
GeoRadiusStore(ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery) *IntCmd
GeoRadiusByMember(ctx context.Context, key, member string, query *GeoRadiusQuery) *GeoLocationCmd
GeoRadiusByMemberStore(ctx context.Context, key, member string, query *GeoRadiusQuery) *IntCmd
GeoSearch(ctx context.Context, key string, q *GeoSearchQuery) *StringSliceCmd
GeoSearchLocation(ctx context.Context, key string, q *GeoSearchLocationQuery) *GeoSearchLocationCmd
GeoSearchStore(ctx context.Context, key, store string, q *GeoSearchStoreQuery) *IntCmd
GeoDist(ctx context.Context, key string, member1, member2, unit string) *FloatCmd
GeoHash(ctx context.Context, key string, members ...string) *StringSliceCmd
}
func (c cmdable) GeoAdd(ctx context.Context, key string, geoLocation ...*GeoLocation) *IntCmd {
args := make([]interface{}, 2+3*len(geoLocation))
args[0] = "geoadd"
args[1] = key
for i, eachLoc := range geoLocation {
args[2+3*i] = eachLoc.Longitude
args[2+3*i+1] = eachLoc.Latitude
args[2+3*i+2] = eachLoc.Name
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// GeoRadius is a read-only GEORADIUS_RO command.
func (c cmdable) GeoRadius(
ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery,
) *GeoLocationCmd {
cmd := NewGeoLocationCmd(ctx, query, "georadius_ro", key, longitude, latitude)
if query.Store != "" || query.StoreDist != "" {
cmd.SetErr(errors.New("GeoRadius does not support Store or StoreDist"))
return cmd
}
_ = c(ctx, cmd)
return cmd
}
// GeoRadiusStore is a writing GEORADIUS command.
func (c cmdable) GeoRadiusStore(
ctx context.Context, key string, longitude, latitude float64, query *GeoRadiusQuery,
) *IntCmd {
args := geoLocationArgs(query, "georadius", key, longitude, latitude)
cmd := NewIntCmd(ctx, args...)
if query.Store == "" && query.StoreDist == "" {
cmd.SetErr(errors.New("GeoRadiusStore requires Store or StoreDist"))
return cmd
}
_ = c(ctx, cmd)
return cmd
}
// GeoRadiusByMember is a read-only GEORADIUSBYMEMBER_RO command.
func (c cmdable) GeoRadiusByMember(
ctx context.Context, key, member string, query *GeoRadiusQuery,
) *GeoLocationCmd {
cmd := NewGeoLocationCmd(ctx, query, "georadiusbymember_ro", key, member)
if query.Store != "" || query.StoreDist != "" {
cmd.SetErr(errors.New("GeoRadiusByMember does not support Store or StoreDist"))
return cmd
}
_ = c(ctx, cmd)
return cmd
}
// GeoRadiusByMemberStore is a writing GEORADIUSBYMEMBER command.
func (c cmdable) GeoRadiusByMemberStore(
ctx context.Context, key, member string, query *GeoRadiusQuery,
) *IntCmd {
args := geoLocationArgs(query, "georadiusbymember", key, member)
cmd := NewIntCmd(ctx, args...)
if query.Store == "" && query.StoreDist == "" {
cmd.SetErr(errors.New("GeoRadiusByMemberStore requires Store or StoreDist"))
return cmd
}
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) GeoSearch(ctx context.Context, key string, q *GeoSearchQuery) *StringSliceCmd {
args := make([]interface{}, 0, 13)
args = append(args, "geosearch", key)
args = geoSearchArgs(q, args)
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) GeoSearchLocation(
ctx context.Context, key string, q *GeoSearchLocationQuery,
) *GeoSearchLocationCmd {
args := make([]interface{}, 0, 16)
args = append(args, "geosearch", key)
args = geoSearchLocationArgs(q, args)
cmd := NewGeoSearchLocationCmd(ctx, q, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) GeoSearchStore(ctx context.Context, key, store string, q *GeoSearchStoreQuery) *IntCmd {
args := make([]interface{}, 0, 15)
args = append(args, "geosearchstore", store, key)
args = geoSearchArgs(&q.GeoSearchQuery, args)
if q.StoreDist {
args = append(args, "storedist")
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) GeoDist(
ctx context.Context, key string, member1, member2, unit string,
) *FloatCmd {
if unit == "" {
unit = "km"
}
cmd := NewFloatCmd(ctx, "geodist", key, member1, member2, unit)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) GeoHash(ctx context.Context, key string, members ...string) *StringSliceCmd {
args := make([]interface{}, 2+len(members))
args[0] = "geohash"
args[1] = key
for i, member := range members {
args[2+i] = member
}
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) GeoPos(ctx context.Context, key string, members ...string) *GeoPosCmd {
args := make([]interface{}, 2+len(members))
args[0] = "geopos"
args[1] = key
for i, member := range members {
args[2+i] = member
}
cmd := NewGeoPosCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}

174
vendor/github.com/redis/go-redis/v9/hash_commands.go generated vendored Normal file
View File

@ -0,0 +1,174 @@
package redis
import "context"
type HashCmdable interface {
HDel(ctx context.Context, key string, fields ...string) *IntCmd
HExists(ctx context.Context, key, field string) *BoolCmd
HGet(ctx context.Context, key, field string) *StringCmd
HGetAll(ctx context.Context, key string) *MapStringStringCmd
HIncrBy(ctx context.Context, key, field string, incr int64) *IntCmd
HIncrByFloat(ctx context.Context, key, field string, incr float64) *FloatCmd
HKeys(ctx context.Context, key string) *StringSliceCmd
HLen(ctx context.Context, key string) *IntCmd
HMGet(ctx context.Context, key string, fields ...string) *SliceCmd
HSet(ctx context.Context, key string, values ...interface{}) *IntCmd
HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd
HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd
HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
HVals(ctx context.Context, key string) *StringSliceCmd
HRandField(ctx context.Context, key string, count int) *StringSliceCmd
HRandFieldWithValues(ctx context.Context, key string, count int) *KeyValueSliceCmd
}
func (c cmdable) HDel(ctx context.Context, key string, fields ...string) *IntCmd {
args := make([]interface{}, 2+len(fields))
args[0] = "hdel"
args[1] = key
for i, field := range fields {
args[2+i] = field
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) HExists(ctx context.Context, key, field string) *BoolCmd {
cmd := NewBoolCmd(ctx, "hexists", key, field)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) HGet(ctx context.Context, key, field string) *StringCmd {
cmd := NewStringCmd(ctx, "hget", key, field)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) HGetAll(ctx context.Context, key string) *MapStringStringCmd {
cmd := NewMapStringStringCmd(ctx, "hgetall", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) HIncrBy(ctx context.Context, key, field string, incr int64) *IntCmd {
cmd := NewIntCmd(ctx, "hincrby", key, field, incr)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) HIncrByFloat(ctx context.Context, key, field string, incr float64) *FloatCmd {
cmd := NewFloatCmd(ctx, "hincrbyfloat", key, field, incr)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) HKeys(ctx context.Context, key string) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "hkeys", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) HLen(ctx context.Context, key string) *IntCmd {
cmd := NewIntCmd(ctx, "hlen", key)
_ = c(ctx, cmd)
return cmd
}
// HMGet returns the values for the specified fields in the hash stored at key.
// It returns an interface{} to distinguish between empty string and nil value.
func (c cmdable) HMGet(ctx context.Context, key string, fields ...string) *SliceCmd {
args := make([]interface{}, 2+len(fields))
args[0] = "hmget"
args[1] = key
for i, field := range fields {
args[2+i] = field
}
cmd := NewSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// HSet accepts values in following formats:
//
// - HSet("myhash", "key1", "value1", "key2", "value2")
//
// - HSet("myhash", []string{"key1", "value1", "key2", "value2"})
//
// - HSet("myhash", map[string]interface{}{"key1": "value1", "key2": "value2"})
//
// Playing struct With "redis" tag.
// type MyHash struct { Key1 string `redis:"key1"`; Key2 int `redis:"key2"` }
//
// - HSet("myhash", MyHash{"value1", "value2"}) Warn: redis-server >= 4.0
//
// For struct, can be a structure pointer type, we only parse the field whose tag is redis.
// if you don't want the field to be read, you can use the `redis:"-"` flag to ignore it,
// or you don't need to set the redis tag.
// For the type of structure field, we only support simple data types:
// string, int/uint(8,16,32,64), float(32,64), time.Time(to RFC3339Nano), time.Duration(to Nanoseconds ),
// if you are other more complex or custom data types, please implement the encoding.BinaryMarshaler interface.
//
// Note that in older versions of Redis server(redis-server < 4.0), HSet only supports a single key-value pair.
// redis-docs: https://redis.io/commands/hset (Starting with Redis version 4.0.0: Accepts multiple field and value arguments.)
// If you are using a Struct type and the number of fields is greater than one,
// you will receive an error similar to "ERR wrong number of arguments", you can use HMSet as a substitute.
func (c cmdable) HSet(ctx context.Context, key string, values ...interface{}) *IntCmd {
args := make([]interface{}, 2, 2+len(values))
args[0] = "hset"
args[1] = key
args = appendArgs(args, values)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// HMSet is a deprecated version of HSet left for compatibility with Redis 3.
func (c cmdable) HMSet(ctx context.Context, key string, values ...interface{}) *BoolCmd {
args := make([]interface{}, 2, 2+len(values))
args[0] = "hmset"
args[1] = key
args = appendArgs(args, values)
cmd := NewBoolCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) HSetNX(ctx context.Context, key, field string, value interface{}) *BoolCmd {
cmd := NewBoolCmd(ctx, "hsetnx", key, field, value)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) HVals(ctx context.Context, key string) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "hvals", key)
_ = c(ctx, cmd)
return cmd
}
// HRandField redis-server version >= 6.2.0.
func (c cmdable) HRandField(ctx context.Context, key string, count int) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "hrandfield", key, count)
_ = c(ctx, cmd)
return cmd
}
// HRandFieldWithValues redis-server version >= 6.2.0.
func (c cmdable) HRandFieldWithValues(ctx context.Context, key string, count int) *KeyValueSliceCmd {
cmd := NewKeyValueSliceCmd(ctx, "hrandfield", key, count, "withvalues")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) HScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
args := []interface{}{"hscan", key, cursor}
if match != "" {
args = append(args, "match", match)
}
if count > 0 {
args = append(args, "count", count)
}
cmd := NewScanCmd(ctx, c, args...)
_ = c(ctx, cmd)
return cmd
}

View File

@ -0,0 +1,42 @@
package redis
import "context"
type HyperLogLogCmdable interface {
PFAdd(ctx context.Context, key string, els ...interface{}) *IntCmd
PFCount(ctx context.Context, keys ...string) *IntCmd
PFMerge(ctx context.Context, dest string, keys ...string) *StatusCmd
}
func (c cmdable) PFAdd(ctx context.Context, key string, els ...interface{}) *IntCmd {
args := make([]interface{}, 2, 2+len(els))
args[0] = "pfadd"
args[1] = key
args = appendArgs(args, els)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PFCount(ctx context.Context, keys ...string) *IntCmd {
args := make([]interface{}, 1+len(keys))
args[0] = "pfcount"
for i, key := range keys {
args[1+i] = key
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PFMerge(ctx context.Context, dest string, keys ...string) *StatusCmd {
args := make([]interface{}, 2+len(keys))
args[0] = "pfmerge"
args[1] = dest
for i, key := range keys {
args[2+i] = key
}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}

View File

@ -1,5 +1,4 @@
//go:build linux || darwin || dragonfly || freebsd || netbsd || openbsd || solaris || illumos
// +build linux darwin dragonfly freebsd netbsd openbsd solaris illumos
package pool

View File

@ -1,5 +1,4 @@
//go:build !linux && !darwin && !dragonfly && !freebsd && !netbsd && !openbsd && !solaris && !illumos
// +build !linux,!darwin,!dragonfly,!freebsd,!netbsd,!openbsd,!solaris,!illumos
package pool

View File

@ -15,6 +15,10 @@ var (
// ErrClosed performs any operation on the closed client will return this error.
ErrClosed = errors.New("redis: client is closed")
// ErrPoolExhausted is returned from a pool connection method
// when the maximum number of database connections in the pool has been reached.
ErrPoolExhausted = errors.New("redis: connection pool exhausted")
// ErrPoolTimeout timed out waiting to get a connection from the connection pool.
ErrPoolTimeout = errors.New("redis: connection pool timeout")
)
@ -61,6 +65,7 @@ type Options struct {
PoolTimeout time.Duration
MinIdleConns int
MaxIdleConns int
MaxActiveConns int
ConnMaxIdleTime time.Duration
ConnMaxLifetime time.Duration
}
@ -159,6 +164,14 @@ func (p *ConnPool) NewConn(ctx context.Context) (*Conn, error) {
}
func (p *ConnPool) newConn(ctx context.Context, pooled bool) (*Conn, error) {
if p.closed() {
return nil, ErrClosed
}
if p.cfg.MaxActiveConns > 0 && p.poolSize >= p.cfg.MaxActiveConns {
return nil, ErrPoolExhausted
}
cn, err := p.dialConn(ctx, pooled)
if err != nil {
return nil, err
@ -167,12 +180,6 @@ func (p *ConnPool) newConn(ctx context.Context, pooled bool) (*Conn, error) {
p.connsMu.Lock()
defer p.connsMu.Unlock()
// It is not allowed to add new connections to the closed connection pool.
if p.closed() {
_ = cn.Close()
return nil, ErrClosed
}
p.conns = append(p.conns, cn)
if pooled {
// If pool is full remove the cn on next Put.

View File

@ -1,5 +1,4 @@
//go:build appengine
// +build appengine
package util

View File

@ -1,5 +1,4 @@
//go:build !appengine
// +build !appengine
package util

289
vendor/github.com/redis/go-redis/v9/list_commands.go generated vendored Normal file
View File

@ -0,0 +1,289 @@
package redis
import (
"context"
"strings"
"time"
)
type ListCmdable interface {
BLPop(ctx context.Context, timeout time.Duration, keys ...string) *StringSliceCmd
BLMPop(ctx context.Context, timeout time.Duration, direction string, count int64, keys ...string) *KeyValuesCmd
BRPop(ctx context.Context, timeout time.Duration, keys ...string) *StringSliceCmd
BRPopLPush(ctx context.Context, source, destination string, timeout time.Duration) *StringCmd
LIndex(ctx context.Context, key string, index int64) *StringCmd
LInsert(ctx context.Context, key, op string, pivot, value interface{}) *IntCmd
LInsertBefore(ctx context.Context, key string, pivot, value interface{}) *IntCmd
LInsertAfter(ctx context.Context, key string, pivot, value interface{}) *IntCmd
LLen(ctx context.Context, key string) *IntCmd
LMPop(ctx context.Context, direction string, count int64, keys ...string) *KeyValuesCmd
LPop(ctx context.Context, key string) *StringCmd
LPopCount(ctx context.Context, key string, count int) *StringSliceCmd
LPos(ctx context.Context, key string, value string, args LPosArgs) *IntCmd
LPosCount(ctx context.Context, key string, value string, count int64, args LPosArgs) *IntSliceCmd
LPush(ctx context.Context, key string, values ...interface{}) *IntCmd
LPushX(ctx context.Context, key string, values ...interface{}) *IntCmd
LRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd
LRem(ctx context.Context, key string, count int64, value interface{}) *IntCmd
LSet(ctx context.Context, key string, index int64, value interface{}) *StatusCmd
LTrim(ctx context.Context, key string, start, stop int64) *StatusCmd
RPop(ctx context.Context, key string) *StringCmd
RPopCount(ctx context.Context, key string, count int) *StringSliceCmd
RPopLPush(ctx context.Context, source, destination string) *StringCmd
RPush(ctx context.Context, key string, values ...interface{}) *IntCmd
RPushX(ctx context.Context, key string, values ...interface{}) *IntCmd
LMove(ctx context.Context, source, destination, srcpos, destpos string) *StringCmd
BLMove(ctx context.Context, source, destination, srcpos, destpos string, timeout time.Duration) *StringCmd
}
func (c cmdable) BLPop(ctx context.Context, timeout time.Duration, keys ...string) *StringSliceCmd {
args := make([]interface{}, 1+len(keys)+1)
args[0] = "blpop"
for i, key := range keys {
args[1+i] = key
}
args[len(args)-1] = formatSec(ctx, timeout)
cmd := NewStringSliceCmd(ctx, args...)
cmd.setReadTimeout(timeout)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) BLMPop(ctx context.Context, timeout time.Duration, direction string, count int64, keys ...string) *KeyValuesCmd {
args := make([]interface{}, 3+len(keys), 6+len(keys))
args[0] = "blmpop"
args[1] = formatSec(ctx, timeout)
args[2] = len(keys)
for i, key := range keys {
args[3+i] = key
}
args = append(args, strings.ToLower(direction), "count", count)
cmd := NewKeyValuesCmd(ctx, args...)
cmd.setReadTimeout(timeout)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) BRPop(ctx context.Context, timeout time.Duration, keys ...string) *StringSliceCmd {
args := make([]interface{}, 1+len(keys)+1)
args[0] = "brpop"
for i, key := range keys {
args[1+i] = key
}
args[len(keys)+1] = formatSec(ctx, timeout)
cmd := NewStringSliceCmd(ctx, args...)
cmd.setReadTimeout(timeout)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) BRPopLPush(ctx context.Context, source, destination string, timeout time.Duration) *StringCmd {
cmd := NewStringCmd(
ctx,
"brpoplpush",
source,
destination,
formatSec(ctx, timeout),
)
cmd.setReadTimeout(timeout)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LIndex(ctx context.Context, key string, index int64) *StringCmd {
cmd := NewStringCmd(ctx, "lindex", key, index)
_ = c(ctx, cmd)
return cmd
}
// LMPop Pops one or more elements from the first non-empty list key from the list of provided key names.
// direction: left or right, count: > 0
// example: client.LMPop(ctx, "left", 3, "key1", "key2")
func (c cmdable) LMPop(ctx context.Context, direction string, count int64, keys ...string) *KeyValuesCmd {
args := make([]interface{}, 2+len(keys), 5+len(keys))
args[0] = "lmpop"
args[1] = len(keys)
for i, key := range keys {
args[2+i] = key
}
args = append(args, strings.ToLower(direction), "count", count)
cmd := NewKeyValuesCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LInsert(ctx context.Context, key, op string, pivot, value interface{}) *IntCmd {
cmd := NewIntCmd(ctx, "linsert", key, op, pivot, value)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LInsertBefore(ctx context.Context, key string, pivot, value interface{}) *IntCmd {
cmd := NewIntCmd(ctx, "linsert", key, "before", pivot, value)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LInsertAfter(ctx context.Context, key string, pivot, value interface{}) *IntCmd {
cmd := NewIntCmd(ctx, "linsert", key, "after", pivot, value)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LLen(ctx context.Context, key string) *IntCmd {
cmd := NewIntCmd(ctx, "llen", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LPop(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "lpop", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LPopCount(ctx context.Context, key string, count int) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "lpop", key, count)
_ = c(ctx, cmd)
return cmd
}
type LPosArgs struct {
Rank, MaxLen int64
}
func (c cmdable) LPos(ctx context.Context, key string, value string, a LPosArgs) *IntCmd {
args := []interface{}{"lpos", key, value}
if a.Rank != 0 {
args = append(args, "rank", a.Rank)
}
if a.MaxLen != 0 {
args = append(args, "maxlen", a.MaxLen)
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LPosCount(ctx context.Context, key string, value string, count int64, a LPosArgs) *IntSliceCmd {
args := []interface{}{"lpos", key, value, "count", count}
if a.Rank != 0 {
args = append(args, "rank", a.Rank)
}
if a.MaxLen != 0 {
args = append(args, "maxlen", a.MaxLen)
}
cmd := NewIntSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LPush(ctx context.Context, key string, values ...interface{}) *IntCmd {
args := make([]interface{}, 2, 2+len(values))
args[0] = "lpush"
args[1] = key
args = appendArgs(args, values)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LPushX(ctx context.Context, key string, values ...interface{}) *IntCmd {
args := make([]interface{}, 2, 2+len(values))
args[0] = "lpushx"
args[1] = key
args = appendArgs(args, values)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd {
cmd := NewStringSliceCmd(
ctx,
"lrange",
key,
start,
stop,
)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LRem(ctx context.Context, key string, count int64, value interface{}) *IntCmd {
cmd := NewIntCmd(ctx, "lrem", key, count, value)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LSet(ctx context.Context, key string, index int64, value interface{}) *StatusCmd {
cmd := NewStatusCmd(ctx, "lset", key, index, value)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LTrim(ctx context.Context, key string, start, stop int64) *StatusCmd {
cmd := NewStatusCmd(
ctx,
"ltrim",
key,
start,
stop,
)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) RPop(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "rpop", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) RPopCount(ctx context.Context, key string, count int) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "rpop", key, count)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) RPopLPush(ctx context.Context, source, destination string) *StringCmd {
cmd := NewStringCmd(ctx, "rpoplpush", source, destination)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) RPush(ctx context.Context, key string, values ...interface{}) *IntCmd {
args := make([]interface{}, 2, 2+len(values))
args[0] = "rpush"
args[1] = key
args = appendArgs(args, values)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) RPushX(ctx context.Context, key string, values ...interface{}) *IntCmd {
args := make([]interface{}, 2, 2+len(values))
args[0] = "rpushx"
args[1] = key
args = appendArgs(args, values)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LMove(ctx context.Context, source, destination, srcpos, destpos string) *StringCmd {
cmd := NewStringCmd(ctx, "lmove", source, destination, srcpos, destpos)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) BLMove(
ctx context.Context, source, destination, srcpos, destpos string, timeout time.Duration,
) *StringCmd {
cmd := NewStringCmd(ctx, "blmove", source, destination, srcpos, destpos, formatSec(ctx, timeout))
cmd.setReadTimeout(timeout)
_ = c(ctx, cmd)
return cmd
}

View File

@ -98,8 +98,10 @@ type Options struct {
// Note that FIFO has slightly higher overhead compared to LIFO,
// but it helps closing idle connections faster reducing the pool size.
PoolFIFO bool
// Maximum number of socket connections.
// Base number of socket connections.
// Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS.
// If there is not enough connections in the pool, new connections will be allocated in excess of PoolSize,
// you can limit it through MaxActiveConns
PoolSize int
// Amount of time client waits for connection if all connections
// are busy before returning an error.
@ -112,6 +114,9 @@ type Options struct {
// Maximum number of idle connections.
// Default is 0. the idle connections are not closed by default.
MaxIdleConns int
// Maximum number of connections allocated by the pool at a given time.
// When zero, there is no limit on the number of connections in the pool.
MaxActiveConns int
// ConnMaxIdleTime is the maximum amount of time a connection may be idle.
// Should be less than server's timeout.
//
@ -136,6 +141,9 @@ type Options struct {
// Enables read only queries on slave/follower nodes.
readOnly bool
// // Disable set-lib on connect. Default is false.
DisableIndentity bool
}
func (opt *Options) init() {
@ -499,6 +507,7 @@ func newConnPool(
PoolTimeout: opt.PoolTimeout,
MinIdleConns: opt.MinIdleConns,
MaxIdleConns: opt.MaxIdleConns,
MaxActiveConns: opt.MaxActiveConns,
ConnMaxIdleTime: opt.ConnMaxIdleTime,
ConnMaxLifetime: opt.ConnMaxLifetime,
})

View File

@ -83,7 +83,8 @@ type ClusterOptions struct {
ConnMaxIdleTime time.Duration
ConnMaxLifetime time.Duration
TLSConfig *tls.Config
TLSConfig *tls.Config
DisableIndentity bool // Disable set-lib on connect. Default is false.
}
func (opt *ClusterOptions) init() {
@ -277,15 +278,15 @@ func (opt *ClusterOptions) clientOptions() *Options {
ReadTimeout: opt.ReadTimeout,
WriteTimeout: opt.WriteTimeout,
PoolFIFO: opt.PoolFIFO,
PoolSize: opt.PoolSize,
PoolTimeout: opt.PoolTimeout,
MinIdleConns: opt.MinIdleConns,
MaxIdleConns: opt.MaxIdleConns,
ConnMaxIdleTime: opt.ConnMaxIdleTime,
ConnMaxLifetime: opt.ConnMaxLifetime,
TLSConfig: opt.TLSConfig,
PoolFIFO: opt.PoolFIFO,
PoolSize: opt.PoolSize,
PoolTimeout: opt.PoolTimeout,
MinIdleConns: opt.MinIdleConns,
MaxIdleConns: opt.MaxIdleConns,
ConnMaxIdleTime: opt.ConnMaxIdleTime,
ConnMaxLifetime: opt.ConnMaxLifetime,
DisableIndentity: opt.DisableIndentity,
TLSConfig: opt.TLSConfig,
// If ClusterSlots is populated, then we probably have an artificial
// cluster whose nodes are not in clustering mode (otherwise there isn't
// much use for ClusterSlots config). This means we cannot execute the

View File

@ -0,0 +1,109 @@
package redis
import (
"context"
"sync"
"sync/atomic"
)
func (c *ClusterClient) DBSize(ctx context.Context) *IntCmd {
cmd := NewIntCmd(ctx, "dbsize")
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
var size int64
err := c.ForEachMaster(ctx, func(ctx context.Context, master *Client) error {
n, err := master.DBSize(ctx).Result()
if err != nil {
return err
}
atomic.AddInt64(&size, n)
return nil
})
if err != nil {
cmd.SetErr(err)
} else {
cmd.val = size
}
return nil
})
return cmd
}
func (c *ClusterClient) ScriptLoad(ctx context.Context, script string) *StringCmd {
cmd := NewStringCmd(ctx, "script", "load", script)
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
var mu sync.Mutex
err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error {
val, err := shard.ScriptLoad(ctx, script).Result()
if err != nil {
return err
}
mu.Lock()
if cmd.Val() == "" {
cmd.val = val
}
mu.Unlock()
return nil
})
if err != nil {
cmd.SetErr(err)
}
return nil
})
return cmd
}
func (c *ClusterClient) ScriptFlush(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "script", "flush")
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error {
return shard.ScriptFlush(ctx).Err()
})
if err != nil {
cmd.SetErr(err)
}
return nil
})
return cmd
}
func (c *ClusterClient) ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd {
args := make([]interface{}, 2+len(hashes))
args[0] = "script"
args[1] = "exists"
for i, hash := range hashes {
args[2+i] = hash
}
cmd := NewBoolSliceCmd(ctx, args...)
result := make([]bool, len(hashes))
for i := range result {
result[i] = true
}
_ = c.withProcessHook(ctx, cmd, func(ctx context.Context, _ Cmder) error {
var mu sync.Mutex
err := c.ForEachShard(ctx, func(ctx context.Context, shard *Client) error {
val, err := shard.ScriptExists(ctx, hashes...).Result()
if err != nil {
return err
}
mu.Lock()
for i, v := range val {
result[i] = result[i] && v
}
mu.Unlock()
return nil
})
if err != nil {
cmd.SetErr(err)
} else {
cmd.val = result
}
return nil
})
return cmd
}

View File

@ -1,6 +1,6 @@
{
"name": "redis",
"version": "9.1.0",
"version": "9.2.1",
"main": "index.js",
"repository": "git@github.com:redis/go-redis.git",
"author": "Vladimir Mihailenco <vladimir.webdev@gmail.com>",

View File

@ -7,7 +7,7 @@ import (
"github.com/redis/go-redis/v9/internal/proto"
)
type probabilisticCmdable interface {
type ProbabilisticCmdable interface {
BFAdd(ctx context.Context, key string, element interface{}) *BoolCmd
BFCard(ctx context.Context, key string) *IntCmd
BFExists(ctx context.Context, key string, element interface{}) *BoolCmd
@ -24,7 +24,7 @@ type probabilisticCmdable interface {
BFReserve(ctx context.Context, key string, errorRate float64, capacity int64) *StatusCmd
BFReserveExpansion(ctx context.Context, key string, errorRate float64, capacity, expansion int64) *StatusCmd
BFReserveNonScaling(ctx context.Context, key string, errorRate float64, capacity int64) *StatusCmd
BFReserveArgs(ctx context.Context, key string, options *BFReserveOptions) *StatusCmd
BFReserveWithArgs(ctx context.Context, key string, options *BFReserveOptions) *StatusCmd
BFScanDump(ctx context.Context, key string, iterator int64) *ScanDumpCmd
BFLoadChunk(ctx context.Context, key string, iterator int64, data interface{}) *StatusCmd
@ -38,7 +38,7 @@ type probabilisticCmdable interface {
CFInsertNX(ctx context.Context, key string, options *CFInsertOptions, elements ...interface{}) *IntSliceCmd
CFMExists(ctx context.Context, key string, elements ...interface{}) *BoolSliceCmd
CFReserve(ctx context.Context, key string, capacity int64) *StatusCmd
CFReserveArgs(ctx context.Context, key string, options *CFReserveOptions) *StatusCmd
CFReserveWithArgs(ctx context.Context, key string, options *CFReserveOptions) *StatusCmd
CFReserveExpansion(ctx context.Context, key string, capacity int64, expansion int64) *StatusCmd
CFReserveBucketSize(ctx context.Context, key string, capacity int64, bucketsize int64) *StatusCmd
CFReserveMaxIterations(ctx context.Context, key string, capacity int64, maxiterations int64) *StatusCmd
@ -143,11 +143,11 @@ func (c cmdable) BFReserveNonScaling(ctx context.Context, key string, errorRate
return cmd
}
// BFReserveArgs creates an empty Bloom filter with a single sub-filter
// BFReserveWithArgs creates an empty Bloom filter with a single sub-filter
// for the initial specified capacity and with an upper bound error_rate.
// This function also allows for specifying additional options such as expansion rate and non-scaling behavior.
// For more information - https://redis.io/commands/bf.reserve/
func (c cmdable) BFReserveArgs(ctx context.Context, key string, options *BFReserveOptions) *StatusCmd {
func (c cmdable) BFReserveWithArgs(ctx context.Context, key string, options *BFReserveOptions) *StatusCmd {
args := []interface{}{"BF.RESERVE", key}
if options != nil {
if options.Error != 0 {
@ -310,6 +310,7 @@ func NewBFInfoCmd(ctx context.Context, args ...interface{}) *BFInfoCmd {
func (cmd *BFInfoCmd) SetVal(val BFInfo) {
cmd.val = val
}
func (cmd *BFInfoCmd) String() string {
return cmdString(cmd, cmd.val)
}
@ -493,10 +494,10 @@ func (c cmdable) CFReserveMaxIterations(ctx context.Context, key string, capacit
return cmd
}
// CFReserveArgs creates an empty Cuckoo filter with the specified options.
// CFReserveWithArgs creates an empty Cuckoo filter with the specified options.
// This function allows for specifying additional options such as bucket size and maximum number of iterations.
// For more information - https://redis.io/commands/cf.reserve/
func (c cmdable) CFReserveArgs(ctx context.Context, key string, options *CFReserveOptions) *StatusCmd {
func (c cmdable) CFReserveWithArgs(ctx context.Context, key string, options *CFReserveOptions) *StatusCmd {
args := []interface{}{"CF.RESERVE", key, options.Capacity}
if options.BucketSize != 0 {
args = append(args, "BUCKETSIZE", options.BucketSize)
@ -679,7 +680,7 @@ func (c cmdable) CFInfo(ctx context.Context, key string) *CFInfoCmd {
// For more information - https://redis.io/commands/cf.insert/
func (c cmdable) CFInsert(ctx context.Context, key string, options *CFInsertOptions, elements ...interface{}) *BoolSliceCmd {
args := []interface{}{"CF.INSERT", key}
args = c.getCfInsertArgs(args, options, elements...)
args = c.getCfInsertWithArgs(args, options, elements...)
cmd := NewBoolSliceCmd(ctx, args...)
_ = c(ctx, cmd)
@ -693,14 +694,14 @@ func (c cmdable) CFInsert(ctx context.Context, key string, options *CFInsertOpti
// For more information - https://redis.io/commands/cf.insertnx/
func (c cmdable) CFInsertNX(ctx context.Context, key string, options *CFInsertOptions, elements ...interface{}) *IntSliceCmd {
args := []interface{}{"CF.INSERTNX", key}
args = c.getCfInsertArgs(args, options, elements...)
args = c.getCfInsertWithArgs(args, options, elements...)
cmd := NewIntSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) getCfInsertArgs(args []interface{}, options *CFInsertOptions, elements ...interface{}) []interface{} {
func (c cmdable) getCfInsertWithArgs(args []interface{}, options *CFInsertOptions, elements ...interface{}) []interface{} {
if options != nil {
if options.Capacity != 0 {
args = append(args, "CAPACITY", options.Capacity)

76
vendor/github.com/redis/go-redis/v9/pubsub_commands.go generated vendored Normal file
View File

@ -0,0 +1,76 @@
package redis
import "context"
type PubSubCmdable interface {
Publish(ctx context.Context, channel string, message interface{}) *IntCmd
SPublish(ctx context.Context, channel string, message interface{}) *IntCmd
PubSubChannels(ctx context.Context, pattern string) *StringSliceCmd
PubSubNumSub(ctx context.Context, channels ...string) *MapStringIntCmd
PubSubNumPat(ctx context.Context) *IntCmd
PubSubShardChannels(ctx context.Context, pattern string) *StringSliceCmd
PubSubShardNumSub(ctx context.Context, channels ...string) *MapStringIntCmd
}
// Publish posts the message to the channel.
func (c cmdable) Publish(ctx context.Context, channel string, message interface{}) *IntCmd {
cmd := NewIntCmd(ctx, "publish", channel, message)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SPublish(ctx context.Context, channel string, message interface{}) *IntCmd {
cmd := NewIntCmd(ctx, "spublish", channel, message)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PubSubChannels(ctx context.Context, pattern string) *StringSliceCmd {
args := []interface{}{"pubsub", "channels"}
if pattern != "*" {
args = append(args, pattern)
}
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PubSubNumSub(ctx context.Context, channels ...string) *MapStringIntCmd {
args := make([]interface{}, 2+len(channels))
args[0] = "pubsub"
args[1] = "numsub"
for i, channel := range channels {
args[2+i] = channel
}
cmd := NewMapStringIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PubSubShardChannels(ctx context.Context, pattern string) *StringSliceCmd {
args := []interface{}{"pubsub", "shardchannels"}
if pattern != "*" {
args = append(args, pattern)
}
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PubSubShardNumSub(ctx context.Context, channels ...string) *MapStringIntCmd {
args := make([]interface{}, 2+len(channels))
args[0] = "pubsub"
args[1] = "shardnumsub"
for i, channel := range channels {
args[2+i] = channel
}
cmd := NewMapStringIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) PubSubNumPat(ctx context.Context) *IntCmd {
cmd := NewIntCmd(ctx, "pubsub", "numpat")
_ = c(ctx, cmd)
return cmd
}

View File

@ -299,7 +299,14 @@ func (c *baseClient) initConn(ctx context.Context, cn *pool.Conn) error {
// difficult to rely on error strings to determine all results.
return err
}
if !c.opt.DisableIndentity {
libName := ""
libVer := Version()
libInfo := LibraryInfo{LibName: &libName}
conn.ClientSetInfo(ctx, libInfo)
libInfo = LibraryInfo{LibVer: &libVer}
conn.ClientSetInfo(ctx, libInfo)
}
_, err := conn.Pipelined(ctx, func(pipe Pipeliner) error {
if !auth && password != "" {
if username != "" {

View File

@ -292,7 +292,6 @@ func (c *ringSharding) SetAddrs(addrs map[string]string) {
func (c *ringSharding) newRingShards(
addrs map[string]string, existing *ringShards,
) (shards *ringShards, created, unused map[string]*ringShard) {
shards = &ringShards{m: make(map[string]*ringShard, len(addrs))}
created = make(map[string]*ringShard) // indexed by addr
unused = make(map[string]*ringShard) // indexed by addr

View File

@ -0,0 +1,215 @@
package redis
import "context"
type ScriptingFunctionsCmdable interface {
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd
EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd
ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd
ScriptFlush(ctx context.Context) *StatusCmd
ScriptKill(ctx context.Context) *StatusCmd
ScriptLoad(ctx context.Context, script string) *StringCmd
FunctionLoad(ctx context.Context, code string) *StringCmd
FunctionLoadReplace(ctx context.Context, code string) *StringCmd
FunctionDelete(ctx context.Context, libName string) *StringCmd
FunctionFlush(ctx context.Context) *StringCmd
FunctionKill(ctx context.Context) *StringCmd
FunctionFlushAsync(ctx context.Context) *StringCmd
FunctionList(ctx context.Context, q FunctionListQuery) *FunctionListCmd
FunctionDump(ctx context.Context) *StringCmd
FunctionRestore(ctx context.Context, libDump string) *StringCmd
FunctionStats(ctx context.Context) *FunctionStatsCmd
FCall(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd
FCallRo(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd
FCallRO(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd
}
func (c cmdable) Eval(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd {
return c.eval(ctx, "eval", script, keys, args...)
}
func (c cmdable) EvalRO(ctx context.Context, script string, keys []string, args ...interface{}) *Cmd {
return c.eval(ctx, "eval_ro", script, keys, args...)
}
func (c cmdable) EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd {
return c.eval(ctx, "evalsha", sha1, keys, args...)
}
func (c cmdable) EvalShaRO(ctx context.Context, sha1 string, keys []string, args ...interface{}) *Cmd {
return c.eval(ctx, "evalsha_ro", sha1, keys, args...)
}
func (c cmdable) eval(ctx context.Context, name, payload string, keys []string, args ...interface{}) *Cmd {
cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
cmdArgs[0] = name
cmdArgs[1] = payload
cmdArgs[2] = len(keys)
for i, key := range keys {
cmdArgs[3+i] = key
}
cmdArgs = appendArgs(cmdArgs, args)
cmd := NewCmd(ctx, cmdArgs...)
// it is possible that only args exist without a key.
// rdb.eval(ctx, eval, script, nil, arg1, arg2)
if len(keys) > 0 {
cmd.SetFirstKeyPos(3)
}
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ScriptExists(ctx context.Context, hashes ...string) *BoolSliceCmd {
args := make([]interface{}, 2+len(hashes))
args[0] = "script"
args[1] = "exists"
for i, hash := range hashes {
args[2+i] = hash
}
cmd := NewBoolSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ScriptFlush(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "script", "flush")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ScriptKill(ctx context.Context) *StatusCmd {
cmd := NewStatusCmd(ctx, "script", "kill")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ScriptLoad(ctx context.Context, script string) *StringCmd {
cmd := NewStringCmd(ctx, "script", "load", script)
_ = c(ctx, cmd)
return cmd
}
// ------------------------------------------------------------------------------
// FunctionListQuery is used with FunctionList to query for Redis libraries
//
// LibraryNamePattern - Use an empty string to get all libraries.
// - Use a glob-style pattern to match multiple libraries with a matching name
// - Use a library's full name to match a single library
// WithCode - If true, it will return the code of the library
type FunctionListQuery struct {
LibraryNamePattern string
WithCode bool
}
func (c cmdable) FunctionLoad(ctx context.Context, code string) *StringCmd {
cmd := NewStringCmd(ctx, "function", "load", code)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) FunctionLoadReplace(ctx context.Context, code string) *StringCmd {
cmd := NewStringCmd(ctx, "function", "load", "replace", code)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) FunctionDelete(ctx context.Context, libName string) *StringCmd {
cmd := NewStringCmd(ctx, "function", "delete", libName)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) FunctionFlush(ctx context.Context) *StringCmd {
cmd := NewStringCmd(ctx, "function", "flush")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) FunctionKill(ctx context.Context) *StringCmd {
cmd := NewStringCmd(ctx, "function", "kill")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) FunctionFlushAsync(ctx context.Context) *StringCmd {
cmd := NewStringCmd(ctx, "function", "flush", "async")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) FunctionList(ctx context.Context, q FunctionListQuery) *FunctionListCmd {
args := make([]interface{}, 2, 5)
args[0] = "function"
args[1] = "list"
if q.LibraryNamePattern != "" {
args = append(args, "libraryname", q.LibraryNamePattern)
}
if q.WithCode {
args = append(args, "withcode")
}
cmd := NewFunctionListCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) FunctionDump(ctx context.Context) *StringCmd {
cmd := NewStringCmd(ctx, "function", "dump")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) FunctionRestore(ctx context.Context, libDump string) *StringCmd {
cmd := NewStringCmd(ctx, "function", "restore", libDump)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) FunctionStats(ctx context.Context) *FunctionStatsCmd {
cmd := NewFunctionStatsCmd(ctx, "function", "stats")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) FCall(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd {
cmdArgs := fcallArgs("fcall", function, keys, args...)
cmd := NewCmd(ctx, cmdArgs...)
if len(keys) > 0 {
cmd.SetFirstKeyPos(3)
}
_ = c(ctx, cmd)
return cmd
}
// FCallRo this function simply calls FCallRO,
// Deprecated: to maintain convention FCallRO.
func (c cmdable) FCallRo(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd {
return c.FCallRO(ctx, function, keys, args...)
}
func (c cmdable) FCallRO(ctx context.Context, function string, keys []string, args ...interface{}) *Cmd {
cmdArgs := fcallArgs("fcall_ro", function, keys, args...)
cmd := NewCmd(ctx, cmdArgs...)
if len(keys) > 0 {
cmd.SetFirstKeyPos(3)
}
_ = c(ctx, cmd)
return cmd
}
func fcallArgs(command string, function string, keys []string, args ...interface{}) []interface{} {
cmdArgs := make([]interface{}, 3+len(keys), 3+len(keys)+len(args))
cmdArgs[0] = command
cmdArgs[1] = function
cmdArgs[2] = len(keys)
for i, key := range keys {
cmdArgs[3+i] = key
}
cmdArgs = append(cmdArgs, args...)
return cmdArgs
}

217
vendor/github.com/redis/go-redis/v9/set_commands.go generated vendored Normal file
View File

@ -0,0 +1,217 @@
package redis
import "context"
type SetCmdable interface {
SAdd(ctx context.Context, key string, members ...interface{}) *IntCmd
SCard(ctx context.Context, key string) *IntCmd
SDiff(ctx context.Context, keys ...string) *StringSliceCmd
SDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd
SInter(ctx context.Context, keys ...string) *StringSliceCmd
SInterCard(ctx context.Context, limit int64, keys ...string) *IntCmd
SInterStore(ctx context.Context, destination string, keys ...string) *IntCmd
SIsMember(ctx context.Context, key string, member interface{}) *BoolCmd
SMIsMember(ctx context.Context, key string, members ...interface{}) *BoolSliceCmd
SMembers(ctx context.Context, key string) *StringSliceCmd
SMembersMap(ctx context.Context, key string) *StringStructMapCmd
SMove(ctx context.Context, source, destination string, member interface{}) *BoolCmd
SPop(ctx context.Context, key string) *StringCmd
SPopN(ctx context.Context, key string, count int64) *StringSliceCmd
SRandMember(ctx context.Context, key string) *StringCmd
SRandMemberN(ctx context.Context, key string, count int64) *StringSliceCmd
SRem(ctx context.Context, key string, members ...interface{}) *IntCmd
SScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
SUnion(ctx context.Context, keys ...string) *StringSliceCmd
SUnionStore(ctx context.Context, destination string, keys ...string) *IntCmd
}
//------------------------------------------------------------------------------
func (c cmdable) SAdd(ctx context.Context, key string, members ...interface{}) *IntCmd {
args := make([]interface{}, 2, 2+len(members))
args[0] = "sadd"
args[1] = key
args = appendArgs(args, members)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SCard(ctx context.Context, key string) *IntCmd {
cmd := NewIntCmd(ctx, "scard", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SDiff(ctx context.Context, keys ...string) *StringSliceCmd {
args := make([]interface{}, 1+len(keys))
args[0] = "sdiff"
for i, key := range keys {
args[1+i] = key
}
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd {
args := make([]interface{}, 2+len(keys))
args[0] = "sdiffstore"
args[1] = destination
for i, key := range keys {
args[2+i] = key
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SInter(ctx context.Context, keys ...string) *StringSliceCmd {
args := make([]interface{}, 1+len(keys))
args[0] = "sinter"
for i, key := range keys {
args[1+i] = key
}
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SInterCard(ctx context.Context, limit int64, keys ...string) *IntCmd {
args := make([]interface{}, 4+len(keys))
args[0] = "sintercard"
numkeys := int64(0)
for i, key := range keys {
args[2+i] = key
numkeys++
}
args[1] = numkeys
args[2+numkeys] = "limit"
args[3+numkeys] = limit
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SInterStore(ctx context.Context, destination string, keys ...string) *IntCmd {
args := make([]interface{}, 2+len(keys))
args[0] = "sinterstore"
args[1] = destination
for i, key := range keys {
args[2+i] = key
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SIsMember(ctx context.Context, key string, member interface{}) *BoolCmd {
cmd := NewBoolCmd(ctx, "sismember", key, member)
_ = c(ctx, cmd)
return cmd
}
// SMIsMember Redis `SMISMEMBER key member [member ...]` command.
func (c cmdable) SMIsMember(ctx context.Context, key string, members ...interface{}) *BoolSliceCmd {
args := make([]interface{}, 2, 2+len(members))
args[0] = "smismember"
args[1] = key
args = appendArgs(args, members)
cmd := NewBoolSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// SMembers Redis `SMEMBERS key` command output as a slice.
func (c cmdable) SMembers(ctx context.Context, key string) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "smembers", key)
_ = c(ctx, cmd)
return cmd
}
// SMembersMap Redis `SMEMBERS key` command output as a map.
func (c cmdable) SMembersMap(ctx context.Context, key string) *StringStructMapCmd {
cmd := NewStringStructMapCmd(ctx, "smembers", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SMove(ctx context.Context, source, destination string, member interface{}) *BoolCmd {
cmd := NewBoolCmd(ctx, "smove", source, destination, member)
_ = c(ctx, cmd)
return cmd
}
// SPop Redis `SPOP key` command.
func (c cmdable) SPop(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "spop", key)
_ = c(ctx, cmd)
return cmd
}
// SPopN Redis `SPOP key count` command.
func (c cmdable) SPopN(ctx context.Context, key string, count int64) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "spop", key, count)
_ = c(ctx, cmd)
return cmd
}
// SRandMember Redis `SRANDMEMBER key` command.
func (c cmdable) SRandMember(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "srandmember", key)
_ = c(ctx, cmd)
return cmd
}
// SRandMemberN Redis `SRANDMEMBER key count` command.
func (c cmdable) SRandMemberN(ctx context.Context, key string, count int64) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "srandmember", key, count)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SRem(ctx context.Context, key string, members ...interface{}) *IntCmd {
args := make([]interface{}, 2, 2+len(members))
args[0] = "srem"
args[1] = key
args = appendArgs(args, members)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SUnion(ctx context.Context, keys ...string) *StringSliceCmd {
args := make([]interface{}, 1+len(keys))
args[0] = "sunion"
for i, key := range keys {
args[1+i] = key
}
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SUnionStore(ctx context.Context, destination string, keys ...string) *IntCmd {
args := make([]interface{}, 2+len(keys))
args[0] = "sunionstore"
args[1] = destination
for i, key := range keys {
args[2+i] = key
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
args := []interface{}{"sscan", key, cursor}
if match != "" {
args = append(args, "match", match)
}
if count > 0 {
args = append(args, "count", count)
}
cmd := NewScanCmd(ctx, c, args...)
_ = c(ctx, cmd)
return cmd
}

View File

@ -0,0 +1,772 @@
package redis
import (
"context"
"strings"
"time"
)
type SortedSetCmdable interface {
BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd
BZMPop(ctx context.Context, timeout time.Duration, order string, count int64, keys ...string) *ZSliceWithKeyCmd
ZAdd(ctx context.Context, key string, members ...Z) *IntCmd
ZAddLT(ctx context.Context, key string, members ...Z) *IntCmd
ZAddGT(ctx context.Context, key string, members ...Z) *IntCmd
ZAddNX(ctx context.Context, key string, members ...Z) *IntCmd
ZAddXX(ctx context.Context, key string, members ...Z) *IntCmd
ZAddArgs(ctx context.Context, key string, args ZAddArgs) *IntCmd
ZAddArgsIncr(ctx context.Context, key string, args ZAddArgs) *FloatCmd
ZCard(ctx context.Context, key string) *IntCmd
ZCount(ctx context.Context, key, min, max string) *IntCmd
ZLexCount(ctx context.Context, key, min, max string) *IntCmd
ZIncrBy(ctx context.Context, key string, increment float64, member string) *FloatCmd
ZInter(ctx context.Context, store *ZStore) *StringSliceCmd
ZInterWithScores(ctx context.Context, store *ZStore) *ZSliceCmd
ZInterCard(ctx context.Context, limit int64, keys ...string) *IntCmd
ZInterStore(ctx context.Context, destination string, store *ZStore) *IntCmd
ZMPop(ctx context.Context, order string, count int64, keys ...string) *ZSliceWithKeyCmd
ZMScore(ctx context.Context, key string, members ...string) *FloatSliceCmd
ZPopMax(ctx context.Context, key string, count ...int64) *ZSliceCmd
ZPopMin(ctx context.Context, key string, count ...int64) *ZSliceCmd
ZRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd
ZRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd
ZRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
ZRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
ZRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd
ZRangeArgs(ctx context.Context, z ZRangeArgs) *StringSliceCmd
ZRangeArgsWithScores(ctx context.Context, z ZRangeArgs) *ZSliceCmd
ZRangeStore(ctx context.Context, dst string, z ZRangeArgs) *IntCmd
ZRank(ctx context.Context, key, member string) *IntCmd
ZRankWithScore(ctx context.Context, key, member string) *RankWithScoreCmd
ZRem(ctx context.Context, key string, members ...interface{}) *IntCmd
ZRemRangeByRank(ctx context.Context, key string, start, stop int64) *IntCmd
ZRemRangeByScore(ctx context.Context, key, min, max string) *IntCmd
ZRemRangeByLex(ctx context.Context, key, min, max string) *IntCmd
ZRevRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd
ZRevRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd
ZRevRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
ZRevRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd
ZRevRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd
ZRevRank(ctx context.Context, key, member string) *IntCmd
ZRevRankWithScore(ctx context.Context, key, member string) *RankWithScoreCmd
ZScore(ctx context.Context, key, member string) *FloatCmd
ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd
ZRandMember(ctx context.Context, key string, count int) *StringSliceCmd
ZRandMemberWithScores(ctx context.Context, key string, count int) *ZSliceCmd
ZUnion(ctx context.Context, store ZStore) *StringSliceCmd
ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd
ZDiff(ctx context.Context, keys ...string) *StringSliceCmd
ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd
ZDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd
ZScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd
}
// BZPopMax Redis `BZPOPMAX key [key ...] timeout` command.
func (c cmdable) BZPopMax(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd {
args := make([]interface{}, 1+len(keys)+1)
args[0] = "bzpopmax"
for i, key := range keys {
args[1+i] = key
}
args[len(args)-1] = formatSec(ctx, timeout)
cmd := NewZWithKeyCmd(ctx, args...)
cmd.setReadTimeout(timeout)
_ = c(ctx, cmd)
return cmd
}
// BZPopMin Redis `BZPOPMIN key [key ...] timeout` command.
func (c cmdable) BZPopMin(ctx context.Context, timeout time.Duration, keys ...string) *ZWithKeyCmd {
args := make([]interface{}, 1+len(keys)+1)
args[0] = "bzpopmin"
for i, key := range keys {
args[1+i] = key
}
args[len(args)-1] = formatSec(ctx, timeout)
cmd := NewZWithKeyCmd(ctx, args...)
cmd.setReadTimeout(timeout)
_ = c(ctx, cmd)
return cmd
}
// BZMPop is the blocking variant of ZMPOP.
// When any of the sorted sets contains elements, this command behaves exactly like ZMPOP.
// When all sorted sets are empty, Redis will block the connection until another client adds members to one of the keys or until the timeout elapses.
// A timeout of zero can be used to block indefinitely.
// example: client.BZMPop(ctx, 0,"max", 1, "set")
func (c cmdable) BZMPop(ctx context.Context, timeout time.Duration, order string, count int64, keys ...string) *ZSliceWithKeyCmd {
args := make([]interface{}, 3+len(keys), 6+len(keys))
args[0] = "bzmpop"
args[1] = formatSec(ctx, timeout)
args[2] = len(keys)
for i, key := range keys {
args[3+i] = key
}
args = append(args, strings.ToLower(order), "count", count)
cmd := NewZSliceWithKeyCmd(ctx, args...)
cmd.setReadTimeout(timeout)
_ = c(ctx, cmd)
return cmd
}
// ZAddArgs WARN: The GT, LT and NX options are mutually exclusive.
type ZAddArgs struct {
NX bool
XX bool
LT bool
GT bool
Ch bool
Members []Z
}
func (c cmdable) zAddArgs(key string, args ZAddArgs, incr bool) []interface{} {
a := make([]interface{}, 0, 6+2*len(args.Members))
a = append(a, "zadd", key)
// The GT, LT and NX options are mutually exclusive.
if args.NX {
a = append(a, "nx")
} else {
if args.XX {
a = append(a, "xx")
}
if args.GT {
a = append(a, "gt")
} else if args.LT {
a = append(a, "lt")
}
}
if args.Ch {
a = append(a, "ch")
}
if incr {
a = append(a, "incr")
}
for _, m := range args.Members {
a = append(a, m.Score)
a = append(a, m.Member)
}
return a
}
func (c cmdable) ZAddArgs(ctx context.Context, key string, args ZAddArgs) *IntCmd {
cmd := NewIntCmd(ctx, c.zAddArgs(key, args, false)...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZAddArgsIncr(ctx context.Context, key string, args ZAddArgs) *FloatCmd {
cmd := NewFloatCmd(ctx, c.zAddArgs(key, args, true)...)
_ = c(ctx, cmd)
return cmd
}
// ZAdd Redis `ZADD key score member [score member ...]` command.
func (c cmdable) ZAdd(ctx context.Context, key string, members ...Z) *IntCmd {
return c.ZAddArgs(ctx, key, ZAddArgs{
Members: members,
})
}
// ZAddLT Redis `ZADD key LT score member [score member ...]` command.
func (c cmdable) ZAddLT(ctx context.Context, key string, members ...Z) *IntCmd {
return c.ZAddArgs(ctx, key, ZAddArgs{
LT: true,
Members: members,
})
}
// ZAddGT Redis `ZADD key GT score member [score member ...]` command.
func (c cmdable) ZAddGT(ctx context.Context, key string, members ...Z) *IntCmd {
return c.ZAddArgs(ctx, key, ZAddArgs{
GT: true,
Members: members,
})
}
// ZAddNX Redis `ZADD key NX score member [score member ...]` command.
func (c cmdable) ZAddNX(ctx context.Context, key string, members ...Z) *IntCmd {
return c.ZAddArgs(ctx, key, ZAddArgs{
NX: true,
Members: members,
})
}
// ZAddXX Redis `ZADD key XX score member [score member ...]` command.
func (c cmdable) ZAddXX(ctx context.Context, key string, members ...Z) *IntCmd {
return c.ZAddArgs(ctx, key, ZAddArgs{
XX: true,
Members: members,
})
}
func (c cmdable) ZCard(ctx context.Context, key string) *IntCmd {
cmd := NewIntCmd(ctx, "zcard", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZCount(ctx context.Context, key, min, max string) *IntCmd {
cmd := NewIntCmd(ctx, "zcount", key, min, max)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZLexCount(ctx context.Context, key, min, max string) *IntCmd {
cmd := NewIntCmd(ctx, "zlexcount", key, min, max)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZIncrBy(ctx context.Context, key string, increment float64, member string) *FloatCmd {
cmd := NewFloatCmd(ctx, "zincrby", key, increment, member)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZInterStore(ctx context.Context, destination string, store *ZStore) *IntCmd {
args := make([]interface{}, 0, 3+store.len())
args = append(args, "zinterstore", destination, len(store.Keys))
args = store.appendArgs(args)
cmd := NewIntCmd(ctx, args...)
cmd.SetFirstKeyPos(3)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZInter(ctx context.Context, store *ZStore) *StringSliceCmd {
args := make([]interface{}, 0, 2+store.len())
args = append(args, "zinter", len(store.Keys))
args = store.appendArgs(args)
cmd := NewStringSliceCmd(ctx, args...)
cmd.SetFirstKeyPos(2)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZInterWithScores(ctx context.Context, store *ZStore) *ZSliceCmd {
args := make([]interface{}, 0, 3+store.len())
args = append(args, "zinter", len(store.Keys))
args = store.appendArgs(args)
args = append(args, "withscores")
cmd := NewZSliceCmd(ctx, args...)
cmd.SetFirstKeyPos(2)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZInterCard(ctx context.Context, limit int64, keys ...string) *IntCmd {
args := make([]interface{}, 4+len(keys))
args[0] = "zintercard"
numkeys := int64(0)
for i, key := range keys {
args[2+i] = key
numkeys++
}
args[1] = numkeys
args[2+numkeys] = "limit"
args[3+numkeys] = limit
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// ZMPop Pops one or more elements with the highest or lowest score from the first non-empty sorted set key from the list of provided key names.
// direction: "max" (highest score) or "min" (lowest score), count: > 0
// example: client.ZMPop(ctx, "max", 5, "set1", "set2")
func (c cmdable) ZMPop(ctx context.Context, order string, count int64, keys ...string) *ZSliceWithKeyCmd {
args := make([]interface{}, 2+len(keys), 5+len(keys))
args[0] = "zmpop"
args[1] = len(keys)
for i, key := range keys {
args[2+i] = key
}
args = append(args, strings.ToLower(order), "count", count)
cmd := NewZSliceWithKeyCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZMScore(ctx context.Context, key string, members ...string) *FloatSliceCmd {
args := make([]interface{}, 2+len(members))
args[0] = "zmscore"
args[1] = key
for i, member := range members {
args[2+i] = member
}
cmd := NewFloatSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZPopMax(ctx context.Context, key string, count ...int64) *ZSliceCmd {
args := []interface{}{
"zpopmax",
key,
}
switch len(count) {
case 0:
break
case 1:
args = append(args, count[0])
default:
panic("too many arguments")
}
cmd := NewZSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZPopMin(ctx context.Context, key string, count ...int64) *ZSliceCmd {
args := []interface{}{
"zpopmin",
key,
}
switch len(count) {
case 0:
break
case 1:
args = append(args, count[0])
default:
panic("too many arguments")
}
cmd := NewZSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// ZRangeArgs is all the options of the ZRange command.
// In version> 6.2.0, you can replace the(cmd):
//
// ZREVRANGE,
// ZRANGEBYSCORE,
// ZREVRANGEBYSCORE,
// ZRANGEBYLEX,
// ZREVRANGEBYLEX.
//
// Please pay attention to your redis-server version.
//
// Rev, ByScore, ByLex and Offset+Count options require redis-server 6.2.0 and higher.
type ZRangeArgs struct {
Key string
// When the ByScore option is provided, the open interval(exclusive) can be set.
// By default, the score intervals specified by <Start> and <Stop> are closed (inclusive).
// It is similar to the deprecated(6.2.0+) ZRangeByScore command.
// For example:
// ZRangeArgs{
// Key: "example-key",
// Start: "(3",
// Stop: 8,
// ByScore: true,
// }
// cmd: "ZRange example-key (3 8 ByScore" (3 < score <= 8).
//
// For the ByLex option, it is similar to the deprecated(6.2.0+) ZRangeByLex command.
// You can set the <Start> and <Stop> options as follows:
// ZRangeArgs{
// Key: "example-key",
// Start: "[abc",
// Stop: "(def",
// ByLex: true,
// }
// cmd: "ZRange example-key [abc (def ByLex"
//
// For normal cases (ByScore==false && ByLex==false), <Start> and <Stop> should be set to the index range (int).
// You can read the documentation for more information: https://redis.io/commands/zrange
Start interface{}
Stop interface{}
// The ByScore and ByLex options are mutually exclusive.
ByScore bool
ByLex bool
Rev bool
// limit offset count.
Offset int64
Count int64
}
func (z ZRangeArgs) appendArgs(args []interface{}) []interface{} {
// For Rev+ByScore/ByLex, we need to adjust the position of <Start> and <Stop>.
if z.Rev && (z.ByScore || z.ByLex) {
args = append(args, z.Key, z.Stop, z.Start)
} else {
args = append(args, z.Key, z.Start, z.Stop)
}
if z.ByScore {
args = append(args, "byscore")
} else if z.ByLex {
args = append(args, "bylex")
}
if z.Rev {
args = append(args, "rev")
}
if z.Offset != 0 || z.Count != 0 {
args = append(args, "limit", z.Offset, z.Count)
}
return args
}
func (c cmdable) ZRangeArgs(ctx context.Context, z ZRangeArgs) *StringSliceCmd {
args := make([]interface{}, 0, 9)
args = append(args, "zrange")
args = z.appendArgs(args)
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRangeArgsWithScores(ctx context.Context, z ZRangeArgs) *ZSliceCmd {
args := make([]interface{}, 0, 10)
args = append(args, "zrange")
args = z.appendArgs(args)
args = append(args, "withscores")
cmd := NewZSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd {
return c.ZRangeArgs(ctx, ZRangeArgs{
Key: key,
Start: start,
Stop: stop,
})
}
func (c cmdable) ZRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd {
return c.ZRangeArgsWithScores(ctx, ZRangeArgs{
Key: key,
Start: start,
Stop: stop,
})
}
type ZRangeBy struct {
Min, Max string
Offset, Count int64
}
func (c cmdable) zRangeBy(ctx context.Context, zcmd, key string, opt *ZRangeBy, withScores bool) *StringSliceCmd {
args := []interface{}{zcmd, key, opt.Min, opt.Max}
if withScores {
args = append(args, "withscores")
}
if opt.Offset != 0 || opt.Count != 0 {
args = append(
args,
"limit",
opt.Offset,
opt.Count,
)
}
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd {
return c.zRangeBy(ctx, "zrangebyscore", key, opt, false)
}
func (c cmdable) ZRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd {
return c.zRangeBy(ctx, "zrangebylex", key, opt, false)
}
func (c cmdable) ZRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd {
args := []interface{}{"zrangebyscore", key, opt.Min, opt.Max, "withscores"}
if opt.Offset != 0 || opt.Count != 0 {
args = append(
args,
"limit",
opt.Offset,
opt.Count,
)
}
cmd := NewZSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRangeStore(ctx context.Context, dst string, z ZRangeArgs) *IntCmd {
args := make([]interface{}, 0, 10)
args = append(args, "zrangestore", dst)
args = z.appendArgs(args)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRank(ctx context.Context, key, member string) *IntCmd {
cmd := NewIntCmd(ctx, "zrank", key, member)
_ = c(ctx, cmd)
return cmd
}
// ZRankWithScore according to the Redis documentation, if member does not exist
// in the sorted set or key does not exist, it will return a redis.Nil error.
func (c cmdable) ZRankWithScore(ctx context.Context, key, member string) *RankWithScoreCmd {
cmd := NewRankWithScoreCmd(ctx, "zrank", key, member, "withscore")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRem(ctx context.Context, key string, members ...interface{}) *IntCmd {
args := make([]interface{}, 2, 2+len(members))
args[0] = "zrem"
args[1] = key
args = appendArgs(args, members)
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRemRangeByRank(ctx context.Context, key string, start, stop int64) *IntCmd {
cmd := NewIntCmd(
ctx,
"zremrangebyrank",
key,
start,
stop,
)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRemRangeByScore(ctx context.Context, key, min, max string) *IntCmd {
cmd := NewIntCmd(ctx, "zremrangebyscore", key, min, max)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRemRangeByLex(ctx context.Context, key, min, max string) *IntCmd {
cmd := NewIntCmd(ctx, "zremrangebylex", key, min, max)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRevRange(ctx context.Context, key string, start, stop int64) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "zrevrange", key, start, stop)
_ = c(ctx, cmd)
return cmd
}
// ZRevRangeWithScores according to the Redis documentation, if member does not exist
// in the sorted set or key does not exist, it will return a redis.Nil error.
func (c cmdable) ZRevRangeWithScores(ctx context.Context, key string, start, stop int64) *ZSliceCmd {
cmd := NewZSliceCmd(ctx, "zrevrange", key, start, stop, "withscores")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) zRevRangeBy(ctx context.Context, zcmd, key string, opt *ZRangeBy) *StringSliceCmd {
args := []interface{}{zcmd, key, opt.Max, opt.Min}
if opt.Offset != 0 || opt.Count != 0 {
args = append(
args,
"limit",
opt.Offset,
opt.Count,
)
}
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRevRangeByScore(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd {
return c.zRevRangeBy(ctx, "zrevrangebyscore", key, opt)
}
func (c cmdable) ZRevRangeByLex(ctx context.Context, key string, opt *ZRangeBy) *StringSliceCmd {
return c.zRevRangeBy(ctx, "zrevrangebylex", key, opt)
}
func (c cmdable) ZRevRangeByScoreWithScores(ctx context.Context, key string, opt *ZRangeBy) *ZSliceCmd {
args := []interface{}{"zrevrangebyscore", key, opt.Max, opt.Min, "withscores"}
if opt.Offset != 0 || opt.Count != 0 {
args = append(
args,
"limit",
opt.Offset,
opt.Count,
)
}
cmd := NewZSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRevRank(ctx context.Context, key, member string) *IntCmd {
cmd := NewIntCmd(ctx, "zrevrank", key, member)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZRevRankWithScore(ctx context.Context, key, member string) *RankWithScoreCmd {
cmd := NewRankWithScoreCmd(ctx, "zrevrank", key, member, "withscore")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZScore(ctx context.Context, key, member string) *FloatCmd {
cmd := NewFloatCmd(ctx, "zscore", key, member)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZUnion(ctx context.Context, store ZStore) *StringSliceCmd {
args := make([]interface{}, 0, 2+store.len())
args = append(args, "zunion", len(store.Keys))
args = store.appendArgs(args)
cmd := NewStringSliceCmd(ctx, args...)
cmd.SetFirstKeyPos(2)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZUnionWithScores(ctx context.Context, store ZStore) *ZSliceCmd {
args := make([]interface{}, 0, 3+store.len())
args = append(args, "zunion", len(store.Keys))
args = store.appendArgs(args)
args = append(args, "withscores")
cmd := NewZSliceCmd(ctx, args...)
cmd.SetFirstKeyPos(2)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZUnionStore(ctx context.Context, dest string, store *ZStore) *IntCmd {
args := make([]interface{}, 0, 3+store.len())
args = append(args, "zunionstore", dest, len(store.Keys))
args = store.appendArgs(args)
cmd := NewIntCmd(ctx, args...)
cmd.SetFirstKeyPos(3)
_ = c(ctx, cmd)
return cmd
}
// ZRandMember redis-server version >= 6.2.0.
func (c cmdable) ZRandMember(ctx context.Context, key string, count int) *StringSliceCmd {
cmd := NewStringSliceCmd(ctx, "zrandmember", key, count)
_ = c(ctx, cmd)
return cmd
}
// ZRandMemberWithScores redis-server version >= 6.2.0.
func (c cmdable) ZRandMemberWithScores(ctx context.Context, key string, count int) *ZSliceCmd {
cmd := NewZSliceCmd(ctx, "zrandmember", key, count, "withscores")
_ = c(ctx, cmd)
return cmd
}
// ZDiff redis-server version >= 6.2.0.
func (c cmdable) ZDiff(ctx context.Context, keys ...string) *StringSliceCmd {
args := make([]interface{}, 2+len(keys))
args[0] = "zdiff"
args[1] = len(keys)
for i, key := range keys {
args[i+2] = key
}
cmd := NewStringSliceCmd(ctx, args...)
cmd.SetFirstKeyPos(2)
_ = c(ctx, cmd)
return cmd
}
// ZDiffWithScores redis-server version >= 6.2.0.
func (c cmdable) ZDiffWithScores(ctx context.Context, keys ...string) *ZSliceCmd {
args := make([]interface{}, 3+len(keys))
args[0] = "zdiff"
args[1] = len(keys)
for i, key := range keys {
args[i+2] = key
}
args[len(keys)+2] = "withscores"
cmd := NewZSliceCmd(ctx, args...)
cmd.SetFirstKeyPos(2)
_ = c(ctx, cmd)
return cmd
}
// ZDiffStore redis-server version >=6.2.0.
func (c cmdable) ZDiffStore(ctx context.Context, destination string, keys ...string) *IntCmd {
args := make([]interface{}, 0, 3+len(keys))
args = append(args, "zdiffstore", destination, len(keys))
for _, key := range keys {
args = append(args, key)
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) ZScan(ctx context.Context, key string, cursor uint64, match string, count int64) *ScanCmd {
args := []interface{}{"zscan", key, cursor}
if match != "" {
args = append(args, "match", match)
}
if count > 0 {
args = append(args, "count", count)
}
cmd := NewScanCmd(ctx, c, args...)
_ = c(ctx, cmd)
return cmd
}
// Z represents sorted set member.
type Z struct {
Score float64
Member interface{}
}
// ZWithKey represents sorted set member including the name of the key where it was popped.
type ZWithKey struct {
Z
Key string
}
// ZStore is used as an arg to ZInter/ZInterStore and ZUnion/ZUnionStore.
type ZStore struct {
Keys []string
Weights []float64
// Can be SUM, MIN or MAX.
Aggregate string
}
func (z ZStore) len() (n int) {
n = len(z.Keys)
if len(z.Weights) > 0 {
n += 1 + len(z.Weights)
}
if z.Aggregate != "" {
n += 2
}
return n
}
func (z ZStore) appendArgs(args []interface{}) []interface{} {
for _, key := range z.Keys {
args = append(args, key)
}
if len(z.Weights) > 0 {
args = append(args, "weights")
for _, weights := range z.Weights {
args = append(args, weights)
}
}
if z.Aggregate != "" {
args = append(args, "aggregate", z.Aggregate)
}
return args
}

438
vendor/github.com/redis/go-redis/v9/stream_commands.go generated vendored Normal file
View File

@ -0,0 +1,438 @@
package redis
import (
"context"
"time"
)
type StreamCmdable interface {
XAdd(ctx context.Context, a *XAddArgs) *StringCmd
XDel(ctx context.Context, stream string, ids ...string) *IntCmd
XLen(ctx context.Context, stream string) *IntCmd
XRange(ctx context.Context, stream, start, stop string) *XMessageSliceCmd
XRangeN(ctx context.Context, stream, start, stop string, count int64) *XMessageSliceCmd
XRevRange(ctx context.Context, stream string, start, stop string) *XMessageSliceCmd
XRevRangeN(ctx context.Context, stream string, start, stop string, count int64) *XMessageSliceCmd
XRead(ctx context.Context, a *XReadArgs) *XStreamSliceCmd
XReadStreams(ctx context.Context, streams ...string) *XStreamSliceCmd
XGroupCreate(ctx context.Context, stream, group, start string) *StatusCmd
XGroupCreateMkStream(ctx context.Context, stream, group, start string) *StatusCmd
XGroupSetID(ctx context.Context, stream, group, start string) *StatusCmd
XGroupDestroy(ctx context.Context, stream, group string) *IntCmd
XGroupCreateConsumer(ctx context.Context, stream, group, consumer string) *IntCmd
XGroupDelConsumer(ctx context.Context, stream, group, consumer string) *IntCmd
XReadGroup(ctx context.Context, a *XReadGroupArgs) *XStreamSliceCmd
XAck(ctx context.Context, stream, group string, ids ...string) *IntCmd
XPending(ctx context.Context, stream, group string) *XPendingCmd
XPendingExt(ctx context.Context, a *XPendingExtArgs) *XPendingExtCmd
XClaim(ctx context.Context, a *XClaimArgs) *XMessageSliceCmd
XClaimJustID(ctx context.Context, a *XClaimArgs) *StringSliceCmd
XAutoClaim(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimCmd
XAutoClaimJustID(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimJustIDCmd
XTrimMaxLen(ctx context.Context, key string, maxLen int64) *IntCmd
XTrimMaxLenApprox(ctx context.Context, key string, maxLen, limit int64) *IntCmd
XTrimMinID(ctx context.Context, key string, minID string) *IntCmd
XTrimMinIDApprox(ctx context.Context, key string, minID string, limit int64) *IntCmd
XInfoGroups(ctx context.Context, key string) *XInfoGroupsCmd
XInfoStream(ctx context.Context, key string) *XInfoStreamCmd
XInfoStreamFull(ctx context.Context, key string, count int) *XInfoStreamFullCmd
XInfoConsumers(ctx context.Context, key string, group string) *XInfoConsumersCmd
}
// XAddArgs accepts values in the following formats:
// - XAddArgs.Values = []interface{}{"key1", "value1", "key2", "value2"}
// - XAddArgs.Values = []string("key1", "value1", "key2", "value2")
// - XAddArgs.Values = map[string]interface{}{"key1": "value1", "key2": "value2"}
//
// Note that map will not preserve the order of key-value pairs.
// MaxLen/MaxLenApprox and MinID are in conflict, only one of them can be used.
type XAddArgs struct {
Stream string
NoMkStream bool
MaxLen int64 // MAXLEN N
MinID string
// Approx causes MaxLen and MinID to use "~" matcher (instead of "=").
Approx bool
Limit int64
ID string
Values interface{}
}
func (c cmdable) XAdd(ctx context.Context, a *XAddArgs) *StringCmd {
args := make([]interface{}, 0, 11)
args = append(args, "xadd", a.Stream)
if a.NoMkStream {
args = append(args, "nomkstream")
}
switch {
case a.MaxLen > 0:
if a.Approx {
args = append(args, "maxlen", "~", a.MaxLen)
} else {
args = append(args, "maxlen", a.MaxLen)
}
case a.MinID != "":
if a.Approx {
args = append(args, "minid", "~", a.MinID)
} else {
args = append(args, "minid", a.MinID)
}
}
if a.Limit > 0 {
args = append(args, "limit", a.Limit)
}
if a.ID != "" {
args = append(args, a.ID)
} else {
args = append(args, "*")
}
args = appendArg(args, a.Values)
cmd := NewStringCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XDel(ctx context.Context, stream string, ids ...string) *IntCmd {
args := []interface{}{"xdel", stream}
for _, id := range ids {
args = append(args, id)
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XLen(ctx context.Context, stream string) *IntCmd {
cmd := NewIntCmd(ctx, "xlen", stream)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XRange(ctx context.Context, stream, start, stop string) *XMessageSliceCmd {
cmd := NewXMessageSliceCmd(ctx, "xrange", stream, start, stop)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XRangeN(ctx context.Context, stream, start, stop string, count int64) *XMessageSliceCmd {
cmd := NewXMessageSliceCmd(ctx, "xrange", stream, start, stop, "count", count)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XRevRange(ctx context.Context, stream, start, stop string) *XMessageSliceCmd {
cmd := NewXMessageSliceCmd(ctx, "xrevrange", stream, start, stop)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XRevRangeN(ctx context.Context, stream, start, stop string, count int64) *XMessageSliceCmd {
cmd := NewXMessageSliceCmd(ctx, "xrevrange", stream, start, stop, "count", count)
_ = c(ctx, cmd)
return cmd
}
type XReadArgs struct {
Streams []string // list of streams and ids, e.g. stream1 stream2 id1 id2
Count int64
Block time.Duration
}
func (c cmdable) XRead(ctx context.Context, a *XReadArgs) *XStreamSliceCmd {
args := make([]interface{}, 0, 6+len(a.Streams))
args = append(args, "xread")
keyPos := int8(1)
if a.Count > 0 {
args = append(args, "count")
args = append(args, a.Count)
keyPos += 2
}
if a.Block >= 0 {
args = append(args, "block")
args = append(args, int64(a.Block/time.Millisecond))
keyPos += 2
}
args = append(args, "streams")
keyPos++
for _, s := range a.Streams {
args = append(args, s)
}
cmd := NewXStreamSliceCmd(ctx, args...)
if a.Block >= 0 {
cmd.setReadTimeout(a.Block)
}
cmd.SetFirstKeyPos(keyPos)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XReadStreams(ctx context.Context, streams ...string) *XStreamSliceCmd {
return c.XRead(ctx, &XReadArgs{
Streams: streams,
Block: -1,
})
}
func (c cmdable) XGroupCreate(ctx context.Context, stream, group, start string) *StatusCmd {
cmd := NewStatusCmd(ctx, "xgroup", "create", stream, group, start)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XGroupCreateMkStream(ctx context.Context, stream, group, start string) *StatusCmd {
cmd := NewStatusCmd(ctx, "xgroup", "create", stream, group, start, "mkstream")
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XGroupSetID(ctx context.Context, stream, group, start string) *StatusCmd {
cmd := NewStatusCmd(ctx, "xgroup", "setid", stream, group, start)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XGroupDestroy(ctx context.Context, stream, group string) *IntCmd {
cmd := NewIntCmd(ctx, "xgroup", "destroy", stream, group)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XGroupCreateConsumer(ctx context.Context, stream, group, consumer string) *IntCmd {
cmd := NewIntCmd(ctx, "xgroup", "createconsumer", stream, group, consumer)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XGroupDelConsumer(ctx context.Context, stream, group, consumer string) *IntCmd {
cmd := NewIntCmd(ctx, "xgroup", "delconsumer", stream, group, consumer)
_ = c(ctx, cmd)
return cmd
}
type XReadGroupArgs struct {
Group string
Consumer string
Streams []string // list of streams and ids, e.g. stream1 stream2 id1 id2
Count int64
Block time.Duration
NoAck bool
}
func (c cmdable) XReadGroup(ctx context.Context, a *XReadGroupArgs) *XStreamSliceCmd {
args := make([]interface{}, 0, 10+len(a.Streams))
args = append(args, "xreadgroup", "group", a.Group, a.Consumer)
keyPos := int8(4)
if a.Count > 0 {
args = append(args, "count", a.Count)
keyPos += 2
}
if a.Block >= 0 {
args = append(args, "block", int64(a.Block/time.Millisecond))
keyPos += 2
}
if a.NoAck {
args = append(args, "noack")
keyPos++
}
args = append(args, "streams")
keyPos++
for _, s := range a.Streams {
args = append(args, s)
}
cmd := NewXStreamSliceCmd(ctx, args...)
if a.Block >= 0 {
cmd.setReadTimeout(a.Block)
}
cmd.SetFirstKeyPos(keyPos)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XAck(ctx context.Context, stream, group string, ids ...string) *IntCmd {
args := []interface{}{"xack", stream, group}
for _, id := range ids {
args = append(args, id)
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XPending(ctx context.Context, stream, group string) *XPendingCmd {
cmd := NewXPendingCmd(ctx, "xpending", stream, group)
_ = c(ctx, cmd)
return cmd
}
type XPendingExtArgs struct {
Stream string
Group string
Idle time.Duration
Start string
End string
Count int64
Consumer string
}
func (c cmdable) XPendingExt(ctx context.Context, a *XPendingExtArgs) *XPendingExtCmd {
args := make([]interface{}, 0, 9)
args = append(args, "xpending", a.Stream, a.Group)
if a.Idle != 0 {
args = append(args, "idle", formatMs(ctx, a.Idle))
}
args = append(args, a.Start, a.End, a.Count)
if a.Consumer != "" {
args = append(args, a.Consumer)
}
cmd := NewXPendingExtCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
type XAutoClaimArgs struct {
Stream string
Group string
MinIdle time.Duration
Start string
Count int64
Consumer string
}
func (c cmdable) XAutoClaim(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimCmd {
args := xAutoClaimArgs(ctx, a)
cmd := NewXAutoClaimCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XAutoClaimJustID(ctx context.Context, a *XAutoClaimArgs) *XAutoClaimJustIDCmd {
args := xAutoClaimArgs(ctx, a)
args = append(args, "justid")
cmd := NewXAutoClaimJustIDCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func xAutoClaimArgs(ctx context.Context, a *XAutoClaimArgs) []interface{} {
args := make([]interface{}, 0, 8)
args = append(args, "xautoclaim", a.Stream, a.Group, a.Consumer, formatMs(ctx, a.MinIdle), a.Start)
if a.Count > 0 {
args = append(args, "count", a.Count)
}
return args
}
type XClaimArgs struct {
Stream string
Group string
Consumer string
MinIdle time.Duration
Messages []string
}
func (c cmdable) XClaim(ctx context.Context, a *XClaimArgs) *XMessageSliceCmd {
args := xClaimArgs(a)
cmd := NewXMessageSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XClaimJustID(ctx context.Context, a *XClaimArgs) *StringSliceCmd {
args := xClaimArgs(a)
args = append(args, "justid")
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
func xClaimArgs(a *XClaimArgs) []interface{} {
args := make([]interface{}, 0, 5+len(a.Messages))
args = append(args,
"xclaim",
a.Stream,
a.Group, a.Consumer,
int64(a.MinIdle/time.Millisecond))
for _, id := range a.Messages {
args = append(args, id)
}
return args
}
// xTrim If approx is true, add the "~" parameter, otherwise it is the default "=" (redis default).
// example:
//
// XTRIM key MAXLEN/MINID threshold LIMIT limit.
// XTRIM key MAXLEN/MINID ~ threshold LIMIT limit.
//
// The redis-server version is lower than 6.2, please set limit to 0.
func (c cmdable) xTrim(
ctx context.Context, key, strategy string,
approx bool, threshold interface{}, limit int64,
) *IntCmd {
args := make([]interface{}, 0, 7)
args = append(args, "xtrim", key, strategy)
if approx {
args = append(args, "~")
}
args = append(args, threshold)
if limit > 0 {
args = append(args, "limit", limit)
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// XTrimMaxLen No `~` rules are used, `limit` cannot be used.
// cmd: XTRIM key MAXLEN maxLen
func (c cmdable) XTrimMaxLen(ctx context.Context, key string, maxLen int64) *IntCmd {
return c.xTrim(ctx, key, "maxlen", false, maxLen, 0)
}
func (c cmdable) XTrimMaxLenApprox(ctx context.Context, key string, maxLen, limit int64) *IntCmd {
return c.xTrim(ctx, key, "maxlen", true, maxLen, limit)
}
func (c cmdable) XTrimMinID(ctx context.Context, key string, minID string) *IntCmd {
return c.xTrim(ctx, key, "minid", false, minID, 0)
}
func (c cmdable) XTrimMinIDApprox(ctx context.Context, key string, minID string, limit int64) *IntCmd {
return c.xTrim(ctx, key, "minid", true, minID, limit)
}
func (c cmdable) XInfoConsumers(ctx context.Context, key string, group string) *XInfoConsumersCmd {
cmd := NewXInfoConsumersCmd(ctx, key, group)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XInfoGroups(ctx context.Context, key string) *XInfoGroupsCmd {
cmd := NewXInfoGroupsCmd(ctx, key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) XInfoStream(ctx context.Context, key string) *XInfoStreamCmd {
cmd := NewXInfoStreamCmd(ctx, key)
_ = c(ctx, cmd)
return cmd
}
// XInfoStreamFull XINFO STREAM FULL [COUNT count]
// redis-server >= 6.0.
func (c cmdable) XInfoStreamFull(ctx context.Context, key string, count int) *XInfoStreamFullCmd {
args := make([]interface{}, 0, 6)
args = append(args, "xinfo", "stream", key, "full")
if count > 0 {
args = append(args, "count", count)
}
cmd := NewXInfoStreamFullCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}

303
vendor/github.com/redis/go-redis/v9/string_commands.go generated vendored Normal file
View File

@ -0,0 +1,303 @@
package redis
import (
"context"
"time"
)
type StringCmdable interface {
Append(ctx context.Context, key, value string) *IntCmd
Decr(ctx context.Context, key string) *IntCmd
DecrBy(ctx context.Context, key string, decrement int64) *IntCmd
Get(ctx context.Context, key string) *StringCmd
GetRange(ctx context.Context, key string, start, end int64) *StringCmd
GetSet(ctx context.Context, key string, value interface{}) *StringCmd
GetEx(ctx context.Context, key string, expiration time.Duration) *StringCmd
GetDel(ctx context.Context, key string) *StringCmd
Incr(ctx context.Context, key string) *IntCmd
IncrBy(ctx context.Context, key string, value int64) *IntCmd
IncrByFloat(ctx context.Context, key string, value float64) *FloatCmd
LCS(ctx context.Context, q *LCSQuery) *LCSCmd
MGet(ctx context.Context, keys ...string) *SliceCmd
MSet(ctx context.Context, values ...interface{}) *StatusCmd
MSetNX(ctx context.Context, values ...interface{}) *BoolCmd
Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd
SetArgs(ctx context.Context, key string, value interface{}, a SetArgs) *StatusCmd
SetEx(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd
SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd
SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd
SetRange(ctx context.Context, key string, offset int64, value string) *IntCmd
StrLen(ctx context.Context, key string) *IntCmd
}
func (c cmdable) Append(ctx context.Context, key, value string) *IntCmd {
cmd := NewIntCmd(ctx, "append", key, value)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Decr(ctx context.Context, key string) *IntCmd {
cmd := NewIntCmd(ctx, "decr", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) DecrBy(ctx context.Context, key string, decrement int64) *IntCmd {
cmd := NewIntCmd(ctx, "decrby", key, decrement)
_ = c(ctx, cmd)
return cmd
}
// Get Redis `GET key` command. It returns redis.Nil error when key does not exist.
func (c cmdable) Get(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "get", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) GetRange(ctx context.Context, key string, start, end int64) *StringCmd {
cmd := NewStringCmd(ctx, "getrange", key, start, end)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) GetSet(ctx context.Context, key string, value interface{}) *StringCmd {
cmd := NewStringCmd(ctx, "getset", key, value)
_ = c(ctx, cmd)
return cmd
}
// GetEx An expiration of zero removes the TTL associated with the key (i.e. GETEX key persist).
// Requires Redis >= 6.2.0.
func (c cmdable) GetEx(ctx context.Context, key string, expiration time.Duration) *StringCmd {
args := make([]interface{}, 0, 4)
args = append(args, "getex", key)
if expiration > 0 {
if usePrecise(expiration) {
args = append(args, "px", formatMs(ctx, expiration))
} else {
args = append(args, "ex", formatSec(ctx, expiration))
}
} else if expiration == 0 {
args = append(args, "persist")
}
cmd := NewStringCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// GetDel redis-server version >= 6.2.0.
func (c cmdable) GetDel(ctx context.Context, key string) *StringCmd {
cmd := NewStringCmd(ctx, "getdel", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) Incr(ctx context.Context, key string) *IntCmd {
cmd := NewIntCmd(ctx, "incr", key)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) IncrBy(ctx context.Context, key string, value int64) *IntCmd {
cmd := NewIntCmd(ctx, "incrby", key, value)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) IncrByFloat(ctx context.Context, key string, value float64) *FloatCmd {
cmd := NewFloatCmd(ctx, "incrbyfloat", key, value)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) LCS(ctx context.Context, q *LCSQuery) *LCSCmd {
cmd := NewLCSCmd(ctx, q)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) MGet(ctx context.Context, keys ...string) *SliceCmd {
args := make([]interface{}, 1+len(keys))
args[0] = "mget"
for i, key := range keys {
args[1+i] = key
}
cmd := NewSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// MSet is like Set but accepts multiple values:
// - MSet("key1", "value1", "key2", "value2")
// - MSet([]string{"key1", "value1", "key2", "value2"})
// - MSet(map[string]interface{}{"key1": "value1", "key2": "value2"})
// - MSet(struct), For struct types, see HSet description.
func (c cmdable) MSet(ctx context.Context, values ...interface{}) *StatusCmd {
args := make([]interface{}, 1, 1+len(values))
args[0] = "mset"
args = appendArgs(args, values)
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// MSetNX is like SetNX but accepts multiple values:
// - MSetNX("key1", "value1", "key2", "value2")
// - MSetNX([]string{"key1", "value1", "key2", "value2"})
// - MSetNX(map[string]interface{}{"key1": "value1", "key2": "value2"})
// - MSetNX(struct), For struct types, see HSet description.
func (c cmdable) MSetNX(ctx context.Context, values ...interface{}) *BoolCmd {
args := make([]interface{}, 1, 1+len(values))
args[0] = "msetnx"
args = appendArgs(args, values)
cmd := NewBoolCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// Set Redis `SET key value [expiration]` command.
// Use expiration for `SETEx`-like behavior.
//
// Zero expiration means the key has no expiration time.
// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
// otherwise you will receive an error: (error) ERR syntax error.
func (c cmdable) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd {
args := make([]interface{}, 3, 5)
args[0] = "set"
args[1] = key
args[2] = value
if expiration > 0 {
if usePrecise(expiration) {
args = append(args, "px", formatMs(ctx, expiration))
} else {
args = append(args, "ex", formatSec(ctx, expiration))
}
} else if expiration == KeepTTL {
args = append(args, "keepttl")
}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// SetArgs provides arguments for the SetArgs function.
type SetArgs struct {
// Mode can be `NX` or `XX` or empty.
Mode string
// Zero `TTL` or `Expiration` means that the key has no expiration time.
TTL time.Duration
ExpireAt time.Time
// When Get is true, the command returns the old value stored at key, or nil when key did not exist.
Get bool
// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
// otherwise you will receive an error: (error) ERR syntax error.
KeepTTL bool
}
// SetArgs supports all the options that the SET command supports.
// It is the alternative to the Set function when you want
// to have more control over the options.
func (c cmdable) SetArgs(ctx context.Context, key string, value interface{}, a SetArgs) *StatusCmd {
args := []interface{}{"set", key, value}
if a.KeepTTL {
args = append(args, "keepttl")
}
if !a.ExpireAt.IsZero() {
args = append(args, "exat", a.ExpireAt.Unix())
}
if a.TTL > 0 {
if usePrecise(a.TTL) {
args = append(args, "px", formatMs(ctx, a.TTL))
} else {
args = append(args, "ex", formatSec(ctx, a.TTL))
}
}
if a.Mode != "" {
args = append(args, a.Mode)
}
if a.Get {
args = append(args, "get")
}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// SetEx Redis `SETEx key expiration value` command.
func (c cmdable) SetEx(ctx context.Context, key string, value interface{}, expiration time.Duration) *StatusCmd {
cmd := NewStatusCmd(ctx, "setex", key, formatSec(ctx, expiration), value)
_ = c(ctx, cmd)
return cmd
}
// SetNX Redis `SET key value [expiration] NX` command.
//
// Zero expiration means the key has no expiration time.
// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
// otherwise you will receive an error: (error) ERR syntax error.
func (c cmdable) SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd {
var cmd *BoolCmd
switch expiration {
case 0:
// Use old `SETNX` to support old Redis versions.
cmd = NewBoolCmd(ctx, "setnx", key, value)
case KeepTTL:
cmd = NewBoolCmd(ctx, "set", key, value, "keepttl", "nx")
default:
if usePrecise(expiration) {
cmd = NewBoolCmd(ctx, "set", key, value, "px", formatMs(ctx, expiration), "nx")
} else {
cmd = NewBoolCmd(ctx, "set", key, value, "ex", formatSec(ctx, expiration), "nx")
}
}
_ = c(ctx, cmd)
return cmd
}
// SetXX Redis `SET key value [expiration] XX` command.
//
// Zero expiration means the key has no expiration time.
// KeepTTL is a Redis KEEPTTL option to keep existing TTL, it requires your redis-server version >= 6.0,
// otherwise you will receive an error: (error) ERR syntax error.
func (c cmdable) SetXX(ctx context.Context, key string, value interface{}, expiration time.Duration) *BoolCmd {
var cmd *BoolCmd
switch expiration {
case 0:
cmd = NewBoolCmd(ctx, "set", key, value, "xx")
case KeepTTL:
cmd = NewBoolCmd(ctx, "set", key, value, "keepttl", "xx")
default:
if usePrecise(expiration) {
cmd = NewBoolCmd(ctx, "set", key, value, "px", formatMs(ctx, expiration), "xx")
} else {
cmd = NewBoolCmd(ctx, "set", key, value, "ex", formatSec(ctx, expiration), "xx")
}
}
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) SetRange(ctx context.Context, key string, offset int64, value string) *IntCmd {
cmd := NewIntCmd(ctx, "setrange", key, offset, value)
_ = c(ctx, cmd)
return cmd
}
func (c cmdable) StrLen(ctx context.Context, key string) *IntCmd {
cmd := NewIntCmd(ctx, "strlen", key)
_ = c(ctx, cmd)
return cmd
}

View File

@ -0,0 +1,920 @@
package redis
import (
"context"
"strconv"
"github.com/redis/go-redis/v9/internal/proto"
)
type TimeseriesCmdable interface {
TSAdd(ctx context.Context, key string, timestamp interface{}, value float64) *IntCmd
TSAddWithArgs(ctx context.Context, key string, timestamp interface{}, value float64, options *TSOptions) *IntCmd
TSCreate(ctx context.Context, key string) *StatusCmd
TSCreateWithArgs(ctx context.Context, key string, options *TSOptions) *StatusCmd
TSAlter(ctx context.Context, key string, options *TSAlterOptions) *StatusCmd
TSCreateRule(ctx context.Context, sourceKey string, destKey string, aggregator Aggregator, bucketDuration int) *StatusCmd
TSCreateRuleWithArgs(ctx context.Context, sourceKey string, destKey string, aggregator Aggregator, bucketDuration int, options *TSCreateRuleOptions) *StatusCmd
TSIncrBy(ctx context.Context, Key string, timestamp float64) *IntCmd
TSIncrByWithArgs(ctx context.Context, key string, timestamp float64, options *TSIncrDecrOptions) *IntCmd
TSDecrBy(ctx context.Context, Key string, timestamp float64) *IntCmd
TSDecrByWithArgs(ctx context.Context, key string, timestamp float64, options *TSIncrDecrOptions) *IntCmd
TSDel(ctx context.Context, Key string, fromTimestamp int, toTimestamp int) *IntCmd
TSDeleteRule(ctx context.Context, sourceKey string, destKey string) *StatusCmd
TSGet(ctx context.Context, key string) *TSTimestampValueCmd
TSGetWithArgs(ctx context.Context, key string, options *TSGetOptions) *TSTimestampValueCmd
TSInfo(ctx context.Context, key string) *MapStringInterfaceCmd
TSInfoWithArgs(ctx context.Context, key string, options *TSInfoOptions) *MapStringInterfaceCmd
TSMAdd(ctx context.Context, ktvSlices [][]interface{}) *IntSliceCmd
TSQueryIndex(ctx context.Context, filterExpr []string) *StringSliceCmd
TSRevRange(ctx context.Context, key string, fromTimestamp int, toTimestamp int) *TSTimestampValueSliceCmd
TSRevRangeWithArgs(ctx context.Context, key string, fromTimestamp int, toTimestamp int, options *TSRevRangeOptions) *TSTimestampValueSliceCmd
TSRange(ctx context.Context, key string, fromTimestamp int, toTimestamp int) *TSTimestampValueSliceCmd
TSRangeWithArgs(ctx context.Context, key string, fromTimestamp int, toTimestamp int, options *TSRangeOptions) *TSTimestampValueSliceCmd
TSMRange(ctx context.Context, fromTimestamp int, toTimestamp int, filterExpr []string) *MapStringSliceInterfaceCmd
TSMRangeWithArgs(ctx context.Context, fromTimestamp int, toTimestamp int, filterExpr []string, options *TSMRangeOptions) *MapStringSliceInterfaceCmd
TSMRevRange(ctx context.Context, fromTimestamp int, toTimestamp int, filterExpr []string) *MapStringSliceInterfaceCmd
TSMRevRangeWithArgs(ctx context.Context, fromTimestamp int, toTimestamp int, filterExpr []string, options *TSMRevRangeOptions) *MapStringSliceInterfaceCmd
TSMGet(ctx context.Context, filters []string) *MapStringSliceInterfaceCmd
TSMGetWithArgs(ctx context.Context, filters []string, options *TSMGetOptions) *MapStringSliceInterfaceCmd
}
type TSOptions struct {
Retention int
ChunkSize int
Encoding string
DuplicatePolicy string
Labels map[string]string
}
type TSIncrDecrOptions struct {
Timestamp int64
Retention int
ChunkSize int
Uncompressed bool
Labels map[string]string
}
type TSAlterOptions struct {
Retention int
ChunkSize int
DuplicatePolicy string
Labels map[string]string
}
type TSCreateRuleOptions struct {
alignTimestamp int64
}
type TSGetOptions struct {
Latest bool
}
type TSInfoOptions struct {
Debug bool
}
type Aggregator int
const (
Invalid = Aggregator(iota)
Avg
Sum
Min
Max
Range
Count
First
Last
StdP
StdS
VarP
VarS
Twa
)
func (a Aggregator) String() string {
switch a {
case Invalid:
return ""
case Avg:
return "AVG"
case Sum:
return "SUM"
case Min:
return "MIN"
case Max:
return "MAX"
case Range:
return "RANGE"
case Count:
return "COUNT"
case First:
return "FIRST"
case Last:
return "LAST"
case StdP:
return "STD.P"
case StdS:
return "STD.S"
case VarP:
return "VAR.P"
case VarS:
return "VAR.S"
case Twa:
return "TWA"
default:
return ""
}
}
type TSRangeOptions struct {
Latest bool
FilterByTS []int
FilterByValue []int
Count int
Align interface{}
Aggregator Aggregator
BucketDuration int
BucketTimestamp interface{}
Empty bool
}
type TSRevRangeOptions struct {
Latest bool
FilterByTS []int
FilterByValue []int
Count int
Align interface{}
Aggregator Aggregator
BucketDuration int
BucketTimestamp interface{}
Empty bool
}
type TSMRangeOptions struct {
Latest bool
FilterByTS []int
FilterByValue []int
WithLabels bool
SelectedLabels []interface{}
Count int
Align interface{}
Aggregator Aggregator
BucketDuration int
BucketTimestamp interface{}
Empty bool
GroupByLabel interface{}
Reducer interface{}
}
type TSMRevRangeOptions struct {
Latest bool
FilterByTS []int
FilterByValue []int
WithLabels bool
SelectedLabels []interface{}
Count int
Align interface{}
Aggregator Aggregator
BucketDuration int
BucketTimestamp interface{}
Empty bool
GroupByLabel interface{}
Reducer interface{}
}
type TSMGetOptions struct {
Latest bool
WithLabels bool
SelectedLabels []interface{}
}
// TSAdd - Adds one or more observations to a t-digest sketch.
// For more information - https://redis.io/commands/ts.add/
func (c cmdable) TSAdd(ctx context.Context, key string, timestamp interface{}, value float64) *IntCmd {
args := []interface{}{"TS.ADD", key, timestamp, value}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSAddWithArgs - Adds one or more observations to a t-digest sketch.
// This function also allows for specifying additional options such as:
// Retention, ChunkSize, Encoding, DuplicatePolicy and Labels.
// For more information - https://redis.io/commands/ts.add/
func (c cmdable) TSAddWithArgs(ctx context.Context, key string, timestamp interface{}, value float64, options *TSOptions) *IntCmd {
args := []interface{}{"TS.ADD", key, timestamp, value}
if options != nil {
if options.Retention != 0 {
args = append(args, "RETENTION", options.Retention)
}
if options.ChunkSize != 0 {
args = append(args, "CHUNK_SIZE", options.ChunkSize)
}
if options.Encoding != "" {
args = append(args, "ENCODING", options.Encoding)
}
if options.DuplicatePolicy != "" {
args = append(args, "DUPLICATE_POLICY", options.DuplicatePolicy)
}
if options.Labels != nil {
args = append(args, "LABELS")
for label, value := range options.Labels {
args = append(args, label, value)
}
}
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSCreate - Creates a new time-series key.
// For more information - https://redis.io/commands/ts.create/
func (c cmdable) TSCreate(ctx context.Context, key string) *StatusCmd {
args := []interface{}{"TS.CREATE", key}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSCreateWithArgs - Creates a new time-series key with additional options.
// This function allows for specifying additional options such as:
// Retention, ChunkSize, Encoding, DuplicatePolicy and Labels.
// For more information - https://redis.io/commands/ts.create/
func (c cmdable) TSCreateWithArgs(ctx context.Context, key string, options *TSOptions) *StatusCmd {
args := []interface{}{"TS.CREATE", key}
if options != nil {
if options.Retention != 0 {
args = append(args, "RETENTION", options.Retention)
}
if options.ChunkSize != 0 {
args = append(args, "CHUNK_SIZE", options.ChunkSize)
}
if options.Encoding != "" {
args = append(args, "ENCODING", options.Encoding)
}
if options.DuplicatePolicy != "" {
args = append(args, "DUPLICATE_POLICY", options.DuplicatePolicy)
}
if options.Labels != nil {
args = append(args, "LABELS")
for label, value := range options.Labels {
args = append(args, label, value)
}
}
}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSAlter - Alters an existing time-series key with additional options.
// This function allows for specifying additional options such as:
// Retention, ChunkSize and DuplicatePolicy.
// For more information - https://redis.io/commands/ts.alter/
func (c cmdable) TSAlter(ctx context.Context, key string, options *TSAlterOptions) *StatusCmd {
args := []interface{}{"TS.ALTER", key}
if options != nil {
if options.Retention != 0 {
args = append(args, "RETENTION", options.Retention)
}
if options.ChunkSize != 0 {
args = append(args, "CHUNK_SIZE", options.ChunkSize)
}
if options.DuplicatePolicy != "" {
args = append(args, "DUPLICATE_POLICY", options.DuplicatePolicy)
}
if options.Labels != nil {
args = append(args, "LABELS")
for label, value := range options.Labels {
args = append(args, label, value)
}
}
}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSCreateRule - Creates a compaction rule from sourceKey to destKey.
// For more information - https://redis.io/commands/ts.createrule/
func (c cmdable) TSCreateRule(ctx context.Context, sourceKey string, destKey string, aggregator Aggregator, bucketDuration int) *StatusCmd {
args := []interface{}{"TS.CREATERULE", sourceKey, destKey, "AGGREGATION", aggregator.String(), bucketDuration}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSCreateRuleWithArgs - Creates a compaction rule from sourceKey to destKey with additional option.
// This function allows for specifying additional option such as:
// alignTimestamp.
// For more information - https://redis.io/commands/ts.createrule/
func (c cmdable) TSCreateRuleWithArgs(ctx context.Context, sourceKey string, destKey string, aggregator Aggregator, bucketDuration int, options *TSCreateRuleOptions) *StatusCmd {
args := []interface{}{"TS.CREATERULE", sourceKey, destKey, "AGGREGATION", aggregator.String(), bucketDuration}
if options != nil {
if options.alignTimestamp != 0 {
args = append(args, options.alignTimestamp)
}
}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSIncrBy - Increments the value of a time-series key by the specified timestamp.
// For more information - https://redis.io/commands/ts.incrby/
func (c cmdable) TSIncrBy(ctx context.Context, Key string, timestamp float64) *IntCmd {
args := []interface{}{"TS.INCRBY", Key, timestamp}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSIncrByWithArgs - Increments the value of a time-series key by the specified timestamp with additional options.
// This function allows for specifying additional options such as:
// Timestamp, Retention, ChunkSize, Uncompressed and Labels.
// For more information - https://redis.io/commands/ts.incrby/
func (c cmdable) TSIncrByWithArgs(ctx context.Context, key string, timestamp float64, options *TSIncrDecrOptions) *IntCmd {
args := []interface{}{"TS.INCRBY", key, timestamp}
if options != nil {
if options.Timestamp != 0 {
args = append(args, "TIMESTAMP", options.Timestamp)
}
if options.Retention != 0 {
args = append(args, "RETENTION", options.Retention)
}
if options.ChunkSize != 0 {
args = append(args, "CHUNK_SIZE", options.ChunkSize)
}
if options.Uncompressed {
args = append(args, "UNCOMPRESSED")
}
if options.Labels != nil {
args = append(args, "LABELS")
for label, value := range options.Labels {
args = append(args, label, value)
}
}
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSDecrBy - Decrements the value of a time-series key by the specified timestamp.
// For more information - https://redis.io/commands/ts.decrby/
func (c cmdable) TSDecrBy(ctx context.Context, Key string, timestamp float64) *IntCmd {
args := []interface{}{"TS.DECRBY", Key, timestamp}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSDecrByWithArgs - Decrements the value of a time-series key by the specified timestamp with additional options.
// This function allows for specifying additional options such as:
// Timestamp, Retention, ChunkSize, Uncompressed and Labels.
// For more information - https://redis.io/commands/ts.decrby/
func (c cmdable) TSDecrByWithArgs(ctx context.Context, key string, timestamp float64, options *TSIncrDecrOptions) *IntCmd {
args := []interface{}{"TS.DECRBY", key, timestamp}
if options != nil {
if options.Timestamp != 0 {
args = append(args, "TIMESTAMP", options.Timestamp)
}
if options.Retention != 0 {
args = append(args, "RETENTION", options.Retention)
}
if options.ChunkSize != 0 {
args = append(args, "CHUNK_SIZE", options.ChunkSize)
}
if options.Uncompressed {
args = append(args, "UNCOMPRESSED")
}
if options.Labels != nil {
args = append(args, "LABELS")
for label, value := range options.Labels {
args = append(args, label, value)
}
}
}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSDel - Deletes a range of samples from a time-series key.
// For more information - https://redis.io/commands/ts.del/
func (c cmdable) TSDel(ctx context.Context, Key string, fromTimestamp int, toTimestamp int) *IntCmd {
args := []interface{}{"TS.DEL", Key, fromTimestamp, toTimestamp}
cmd := NewIntCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSDeleteRule - Deletes a compaction rule from sourceKey to destKey.
// For more information - https://redis.io/commands/ts.deleterule/
func (c cmdable) TSDeleteRule(ctx context.Context, sourceKey string, destKey string) *StatusCmd {
args := []interface{}{"TS.DELETERULE", sourceKey, destKey}
cmd := NewStatusCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSGetWithArgs - Gets the last sample of a time-series key with additional option.
// This function allows for specifying additional option such as:
// Latest.
// For more information - https://redis.io/commands/ts.get/
func (c cmdable) TSGetWithArgs(ctx context.Context, key string, options *TSGetOptions) *TSTimestampValueCmd {
args := []interface{}{"TS.GET", key}
if options != nil {
if options.Latest {
args = append(args, "LATEST")
}
}
cmd := newTSTimestampValueCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSGet - Gets the last sample of a time-series key.
// For more information - https://redis.io/commands/ts.get/
func (c cmdable) TSGet(ctx context.Context, key string) *TSTimestampValueCmd {
args := []interface{}{"TS.GET", key}
cmd := newTSTimestampValueCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
type TSTimestampValue struct {
Timestamp int64
Value float64
}
type TSTimestampValueCmd struct {
baseCmd
val TSTimestampValue
}
func newTSTimestampValueCmd(ctx context.Context, args ...interface{}) *TSTimestampValueCmd {
return &TSTimestampValueCmd{
baseCmd: baseCmd{
ctx: ctx,
args: args,
},
}
}
func (cmd *TSTimestampValueCmd) String() string {
return cmdString(cmd, cmd.val)
}
func (cmd *TSTimestampValueCmd) SetVal(val TSTimestampValue) {
cmd.val = val
}
func (cmd *TSTimestampValueCmd) Result() (TSTimestampValue, error) {
return cmd.val, cmd.err
}
func (cmd *TSTimestampValueCmd) Val() TSTimestampValue {
return cmd.val
}
func (cmd *TSTimestampValueCmd) readReply(rd *proto.Reader) (err error) {
n, err := rd.ReadMapLen()
if err != nil {
return err
}
cmd.val = TSTimestampValue{}
for i := 0; i < n; i++ {
timestamp, err := rd.ReadInt()
if err != nil {
return err
}
value, err := rd.ReadString()
if err != nil {
return err
}
cmd.val.Timestamp = timestamp
cmd.val.Value, err = strconv.ParseFloat(value, 64)
if err != nil {
return err
}
}
return nil
}
// TSInfo - Returns information about a time-series key.
// For more information - https://redis.io/commands/ts.info/
func (c cmdable) TSInfo(ctx context.Context, key string) *MapStringInterfaceCmd {
args := []interface{}{"TS.INFO", key}
cmd := NewMapStringInterfaceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSInfoWithArgs - Returns information about a time-series key with additional option.
// This function allows for specifying additional option such as:
// Debug.
// For more information - https://redis.io/commands/ts.info/
func (c cmdable) TSInfoWithArgs(ctx context.Context, key string, options *TSInfoOptions) *MapStringInterfaceCmd {
args := []interface{}{"TS.INFO", key}
if options != nil {
if options.Debug {
args = append(args, "DEBUG")
}
}
cmd := NewMapStringInterfaceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSMAdd - Adds multiple samples to multiple time-series keys.
// For more information - https://redis.io/commands/ts.madd/
func (c cmdable) TSMAdd(ctx context.Context, ktvSlices [][]interface{}) *IntSliceCmd {
args := []interface{}{"TS.MADD"}
for _, ktv := range ktvSlices {
args = append(args, ktv...)
}
cmd := NewIntSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSQueryIndex - Returns all the keys matching the filter expression.
// For more information - https://redis.io/commands/ts.queryindex/
func (c cmdable) TSQueryIndex(ctx context.Context, filterExpr []string) *StringSliceCmd {
args := []interface{}{"TS.QUERYINDEX"}
for _, f := range filterExpr {
args = append(args, f)
}
cmd := NewStringSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSRevRange - Returns a range of samples from a time-series key in reverse order.
// For more information - https://redis.io/commands/ts.revrange/
func (c cmdable) TSRevRange(ctx context.Context, key string, fromTimestamp int, toTimestamp int) *TSTimestampValueSliceCmd {
args := []interface{}{"TS.REVRANGE", key, fromTimestamp, toTimestamp}
cmd := newTSTimestampValueSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSRevRangeWithArgs - Returns a range of samples from a time-series key in reverse order with additional options.
// This function allows for specifying additional options such as:
// Latest, FilterByTS, FilterByValue, Count, Align, Aggregator,
// BucketDuration, BucketTimestamp and Empty.
// For more information - https://redis.io/commands/ts.revrange/
func (c cmdable) TSRevRangeWithArgs(ctx context.Context, key string, fromTimestamp int, toTimestamp int, options *TSRevRangeOptions) *TSTimestampValueSliceCmd {
args := []interface{}{"TS.REVRANGE", key, fromTimestamp, toTimestamp}
if options != nil {
if options.Latest {
args = append(args, "LATEST")
}
if options.FilterByTS != nil {
args = append(args, "FILTER_BY_TS")
for _, f := range options.FilterByTS {
args = append(args, f)
}
}
if options.FilterByValue != nil {
args = append(args, "FILTER_BY_VALUE")
for _, f := range options.FilterByValue {
args = append(args, f)
}
}
if options.Count != 0 {
args = append(args, "COUNT", options.Count)
}
if options.Align != nil {
args = append(args, "ALIGN", options.Align)
}
if options.Aggregator != 0 {
args = append(args, "AGGREGATION", options.Aggregator.String())
}
if options.BucketDuration != 0 {
args = append(args, options.BucketDuration)
}
if options.BucketTimestamp != nil {
args = append(args, "BUCKETTIMESTAMP", options.BucketTimestamp)
}
if options.Empty {
args = append(args, "EMPTY")
}
}
cmd := newTSTimestampValueSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSRange - Returns a range of samples from a time-series key.
// For more information - https://redis.io/commands/ts.range/
func (c cmdable) TSRange(ctx context.Context, key string, fromTimestamp int, toTimestamp int) *TSTimestampValueSliceCmd {
args := []interface{}{"TS.RANGE", key, fromTimestamp, toTimestamp}
cmd := newTSTimestampValueSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSRangeWithArgs - Returns a range of samples from a time-series key with additional options.
// This function allows for specifying additional options such as:
// Latest, FilterByTS, FilterByValue, Count, Align, Aggregator,
// BucketDuration, BucketTimestamp and Empty.
// For more information - https://redis.io/commands/ts.range/
func (c cmdable) TSRangeWithArgs(ctx context.Context, key string, fromTimestamp int, toTimestamp int, options *TSRangeOptions) *TSTimestampValueSliceCmd {
args := []interface{}{"TS.RANGE", key, fromTimestamp, toTimestamp}
if options != nil {
if options.Latest {
args = append(args, "LATEST")
}
if options.FilterByTS != nil {
args = append(args, "FILTER_BY_TS")
for _, f := range options.FilterByTS {
args = append(args, f)
}
}
if options.FilterByValue != nil {
args = append(args, "FILTER_BY_VALUE")
for _, f := range options.FilterByValue {
args = append(args, f)
}
}
if options.Count != 0 {
args = append(args, "COUNT", options.Count)
}
if options.Align != nil {
args = append(args, "ALIGN", options.Align)
}
if options.Aggregator != 0 {
args = append(args, "AGGREGATION", options.Aggregator.String())
}
if options.BucketDuration != 0 {
args = append(args, options.BucketDuration)
}
if options.BucketTimestamp != nil {
args = append(args, "BUCKETTIMESTAMP", options.BucketTimestamp)
}
if options.Empty {
args = append(args, "EMPTY")
}
}
cmd := newTSTimestampValueSliceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
type TSTimestampValueSliceCmd struct {
baseCmd
val []TSTimestampValue
}
func newTSTimestampValueSliceCmd(ctx context.Context, args ...interface{}) *TSTimestampValueSliceCmd {
return &TSTimestampValueSliceCmd{
baseCmd: baseCmd{
ctx: ctx,
args: args,
},
}
}
func (cmd *TSTimestampValueSliceCmd) String() string {
return cmdString(cmd, cmd.val)
}
func (cmd *TSTimestampValueSliceCmd) SetVal(val []TSTimestampValue) {
cmd.val = val
}
func (cmd *TSTimestampValueSliceCmd) Result() ([]TSTimestampValue, error) {
return cmd.val, cmd.err
}
func (cmd *TSTimestampValueSliceCmd) Val() []TSTimestampValue {
return cmd.val
}
func (cmd *TSTimestampValueSliceCmd) readReply(rd *proto.Reader) (err error) {
n, err := rd.ReadArrayLen()
if err != nil {
return err
}
cmd.val = make([]TSTimestampValue, n)
for i := 0; i < n; i++ {
_, _ = rd.ReadArrayLen()
timestamp, err := rd.ReadInt()
if err != nil {
return err
}
value, err := rd.ReadString()
if err != nil {
return err
}
cmd.val[i].Timestamp = timestamp
cmd.val[i].Value, err = strconv.ParseFloat(value, 64)
if err != nil {
return err
}
}
return nil
}
// TSMRange - Returns a range of samples from multiple time-series keys.
// For more information - https://redis.io/commands/ts.mrange/
func (c cmdable) TSMRange(ctx context.Context, fromTimestamp int, toTimestamp int, filterExpr []string) *MapStringSliceInterfaceCmd {
args := []interface{}{"TS.MRANGE", fromTimestamp, toTimestamp, "FILTER"}
for _, f := range filterExpr {
args = append(args, f)
}
cmd := NewMapStringSliceInterfaceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSMRangeWithArgs - Returns a range of samples from multiple time-series keys with additional options.
// This function allows for specifying additional options such as:
// Latest, FilterByTS, FilterByValue, WithLabels, SelectedLabels,
// Count, Align, Aggregator, BucketDuration, BucketTimestamp,
// Empty, GroupByLabel and Reducer.
// For more information - https://redis.io/commands/ts.mrange/
func (c cmdable) TSMRangeWithArgs(ctx context.Context, fromTimestamp int, toTimestamp int, filterExpr []string, options *TSMRangeOptions) *MapStringSliceInterfaceCmd {
args := []interface{}{"TS.MRANGE", fromTimestamp, toTimestamp}
if options != nil {
if options.Latest {
args = append(args, "LATEST")
}
if options.FilterByTS != nil {
args = append(args, "FILTER_BY_TS")
for _, f := range options.FilterByTS {
args = append(args, f)
}
}
if options.FilterByValue != nil {
args = append(args, "FILTER_BY_VALUE")
for _, f := range options.FilterByValue {
args = append(args, f)
}
}
if options.WithLabels {
args = append(args, "WITHLABELS")
}
if options.SelectedLabels != nil {
args = append(args, "SELECTED_LABELS")
args = append(args, options.SelectedLabels...)
}
if options.Count != 0 {
args = append(args, "COUNT", options.Count)
}
if options.Align != nil {
args = append(args, "ALIGN", options.Align)
}
if options.Aggregator != 0 {
args = append(args, "AGGREGATION", options.Aggregator.String())
}
if options.BucketDuration != 0 {
args = append(args, options.BucketDuration)
}
if options.BucketTimestamp != nil {
args = append(args, "BUCKETTIMESTAMP", options.BucketTimestamp)
}
if options.Empty {
args = append(args, "EMPTY")
}
}
args = append(args, "FILTER")
for _, f := range filterExpr {
args = append(args, f)
}
if options != nil {
if options.GroupByLabel != nil {
args = append(args, "GROUPBY", options.GroupByLabel)
}
if options.Reducer != nil {
args = append(args, "REDUCE", options.Reducer)
}
}
cmd := NewMapStringSliceInterfaceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSMRevRange - Returns a range of samples from multiple time-series keys in reverse order.
// For more information - https://redis.io/commands/ts.mrevrange/
func (c cmdable) TSMRevRange(ctx context.Context, fromTimestamp int, toTimestamp int, filterExpr []string) *MapStringSliceInterfaceCmd {
args := []interface{}{"TS.MREVRANGE", fromTimestamp, toTimestamp, "FILTER"}
for _, f := range filterExpr {
args = append(args, f)
}
cmd := NewMapStringSliceInterfaceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSMRevRangeWithArgs - Returns a range of samples from multiple time-series keys in reverse order with additional options.
// This function allows for specifying additional options such as:
// Latest, FilterByTS, FilterByValue, WithLabels, SelectedLabels,
// Count, Align, Aggregator, BucketDuration, BucketTimestamp,
// Empty, GroupByLabel and Reducer.
// For more information - https://redis.io/commands/ts.mrevrange/
func (c cmdable) TSMRevRangeWithArgs(ctx context.Context, fromTimestamp int, toTimestamp int, filterExpr []string, options *TSMRevRangeOptions) *MapStringSliceInterfaceCmd {
args := []interface{}{"TS.MREVRANGE", fromTimestamp, toTimestamp}
if options != nil {
if options.Latest {
args = append(args, "LATEST")
}
if options.FilterByTS != nil {
args = append(args, "FILTER_BY_TS")
for _, f := range options.FilterByTS {
args = append(args, f)
}
}
if options.FilterByValue != nil {
args = append(args, "FILTER_BY_VALUE")
for _, f := range options.FilterByValue {
args = append(args, f)
}
}
if options.WithLabels {
args = append(args, "WITHLABELS")
}
if options.SelectedLabels != nil {
args = append(args, "SELECTED_LABELS")
args = append(args, options.SelectedLabels...)
}
if options.Count != 0 {
args = append(args, "COUNT", options.Count)
}
if options.Align != nil {
args = append(args, "ALIGN", options.Align)
}
if options.Aggregator != 0 {
args = append(args, "AGGREGATION", options.Aggregator.String())
}
if options.BucketDuration != 0 {
args = append(args, options.BucketDuration)
}
if options.BucketTimestamp != nil {
args = append(args, "BUCKETTIMESTAMP", options.BucketTimestamp)
}
if options.Empty {
args = append(args, "EMPTY")
}
}
args = append(args, "FILTER")
for _, f := range filterExpr {
args = append(args, f)
}
if options != nil {
if options.GroupByLabel != nil {
args = append(args, "GROUPBY", options.GroupByLabel)
}
if options.Reducer != nil {
args = append(args, "REDUCE", options.Reducer)
}
}
cmd := NewMapStringSliceInterfaceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSMGet - Returns the last sample of multiple time-series keys.
// For more information - https://redis.io/commands/ts.mget/
func (c cmdable) TSMGet(ctx context.Context, filters []string) *MapStringSliceInterfaceCmd {
args := []interface{}{"TS.MGET", "FILTER"}
for _, f := range filters {
args = append(args, f)
}
cmd := NewMapStringSliceInterfaceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}
// TSMGetWithArgs - Returns the last sample of multiple time-series keys with additional options.
// This function allows for specifying additional options such as:
// Latest, WithLabels and SelectedLabels.
// For more information - https://redis.io/commands/ts.mget/
func (c cmdable) TSMGetWithArgs(ctx context.Context, filters []string, options *TSMGetOptions) *MapStringSliceInterfaceCmd {
args := []interface{}{"TS.MGET"}
if options != nil {
if options.Latest {
args = append(args, "LATEST")
}
if options.WithLabels {
args = append(args, "WITHLABELS")
}
if options.SelectedLabels != nil {
args = append(args, "SELECTED_LABELS")
args = append(args, options.SelectedLabels...)
}
}
args = append(args, "FILTER")
for _, f := range filters {
args = append(args, f)
}
cmd := NewMapStringSliceInterfaceCmd(ctx, args...)
_ = c(ctx, cmd)
return cmd
}

View File

@ -2,5 +2,5 @@ package redis
// Version is the current release version.
func Version() string {
return "9.1.0"
return "9.2.1"
}

2
vendor/modules.txt vendored
View File

@ -236,7 +236,7 @@ github.com/prometheus/common/model
github.com/prometheus/procfs
github.com/prometheus/procfs/internal/fs
github.com/prometheus/procfs/internal/util
# github.com/redis/go-redis/v9 v9.1.0
# github.com/redis/go-redis/v9 v9.2.1
## explicit; go 1.18
github.com/redis/go-redis/v9
github.com/redis/go-redis/v9/internal