protocol-redis 0.4.2 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/development.yml +34 -0
- data/README.md +1 -1
- data/lib/protocol/redis/methods/scripting.rb +82 -0
- data/lib/protocol/redis/methods/sets.rb +145 -0
- data/lib/protocol/redis/methods/sorted_sets.rb +253 -9
- data/lib/protocol/redis/methods/streams.rb +141 -0
- data/lib/protocol/redis/version.rb +1 -1
- data/protocol-redis.gemspec +9 -10
- metadata +8 -5
- data/.travis.yml +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1be06c92dd3aa593fd22a8e4a437c93d3d74b8cf5308ec7a7721ce48f74d88c5
|
4
|
+
data.tar.gz: eaa6c565377014ffae9c6bcd20b02437f6c83126da57cd12c4d768e54a320c3a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6f473cf7bacd6bc990bd412c544f6911248c1a392412a0c85201b33dd60706e50f4cf6fe84c10f82d6018e3952733491aee1bb0113058201af250979cc6091da
|
7
|
+
data.tar.gz: 468ddc3e83d7da8165bfebacc1c4860407647c5f8ac66129b0c889742da1da35d97e480cfee2007db172000a685d423840a1fffd81d98a4c9ceb44111486173e
|
@@ -0,0 +1,34 @@
|
|
1
|
+
name: Development
|
2
|
+
|
3
|
+
on: [push, pull_request]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
strategy:
|
8
|
+
matrix:
|
9
|
+
os:
|
10
|
+
- ubuntu
|
11
|
+
- macos
|
12
|
+
|
13
|
+
ruby:
|
14
|
+
- 2.4
|
15
|
+
- 2.5
|
16
|
+
- 2.6
|
17
|
+
- 2.7
|
18
|
+
|
19
|
+
include:
|
20
|
+
- os: 'ubuntu'
|
21
|
+
ruby: '2.6'
|
22
|
+
env: COVERAGE=PartialSummary,Coveralls
|
23
|
+
|
24
|
+
runs-on: ${{matrix.os}}-latest
|
25
|
+
|
26
|
+
steps:
|
27
|
+
- uses: actions/checkout@v1
|
28
|
+
- uses: ruby/setup-ruby@v1
|
29
|
+
with:
|
30
|
+
ruby-version: ${{matrix.ruby}}
|
31
|
+
- name: Install dependencies
|
32
|
+
run: bundle install
|
33
|
+
- name: Run tests
|
34
|
+
run: ${{matrix.env}} bundle exec rspec
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Implements the RESP2 and [RESP3](https://github.com/antirez/RESP3) Redis protocols.
|
4
4
|
|
5
|
-
[![
|
5
|
+
[![Actions Status](https://github.com/socketry/protocol-redis/workflows/Development/badge.svg)](https://github.com/socketry/protocol-redis/actions?workflow=Development)
|
6
6
|
|
7
7
|
## Installation
|
8
8
|
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
|
23
|
+
module Protocol
|
24
|
+
module Redis
|
25
|
+
module Methods
|
26
|
+
module Scripting
|
27
|
+
# Execute a Lua script server side. Depends on the script that is executed.
|
28
|
+
# @see https://redis.io/commands/eval
|
29
|
+
# @param script [String]
|
30
|
+
# @param numkeys [Integer]
|
31
|
+
# @param key [Key]
|
32
|
+
# @param arg [String]
|
33
|
+
def eval(*arguments)
|
34
|
+
call("EVAL", *arguments)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Execute a Lua script server side. Depends on the script that is executed.
|
38
|
+
# @see https://redis.io/commands/evalsha
|
39
|
+
# @param sha1 [String]
|
40
|
+
# @param numkeys [Integer]
|
41
|
+
# @param key [Key]
|
42
|
+
# @param arg [String]
|
43
|
+
def evalsha(*arguments)
|
44
|
+
call("EVALSHA", *arguments)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Set the debug mode for executed scripts. O(1).
|
48
|
+
# @see https://redis.io/commands/script debug
|
49
|
+
# @param mode [Enum]
|
50
|
+
def script_debug(*arguments)
|
51
|
+
call("SCRIPT DEBUG", *arguments)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Check existence of scripts in the script cache. O(N) with N being the number of scripts to check (so checking a single script is an O(1) operation).
|
55
|
+
# @see https://redis.io/commands/script exists
|
56
|
+
# @param sha1 [String]
|
57
|
+
def script_exists(*arguments)
|
58
|
+
call("SCRIPT EXISTS", *arguments)
|
59
|
+
end
|
60
|
+
|
61
|
+
# Remove all the scripts from the script cache. O(N) with N being the number of scripts in cache.
|
62
|
+
# @see https://redis.io/commands/script flush
|
63
|
+
def script_flush(*arguments)
|
64
|
+
call("SCRIPT FLUSH", *arguments)
|
65
|
+
end
|
66
|
+
|
67
|
+
# Kill the script currently in execution. O(1).
|
68
|
+
# @see https://redis.io/commands/script kill
|
69
|
+
def script_kill(*arguments)
|
70
|
+
call("SCRIPT KILL", *arguments)
|
71
|
+
end
|
72
|
+
|
73
|
+
# Load the specified Lua script into the script cache. O(N) with N being the length in bytes of the script body.
|
74
|
+
# @see https://redis.io/commands/script load
|
75
|
+
# @param script [String]
|
76
|
+
def script_load(*arguments)
|
77
|
+
call("SCRIPT LOAD", *arguments)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,145 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
|
23
|
+
module Protocol
|
24
|
+
module Redis
|
25
|
+
module Methods
|
26
|
+
module Sets
|
27
|
+
# Add one or more members to a set. O(1) for each element added, so O(N) to add N elements when the command is called with multiple arguments.
|
28
|
+
# @see https://redis.io/commands/sadd
|
29
|
+
# @param key [Key]
|
30
|
+
# @param member [String]
|
31
|
+
def sadd(*arguments)
|
32
|
+
call("SADD", *arguments)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Get the number of members in a set. O(1).
|
36
|
+
# @see https://redis.io/commands/scard
|
37
|
+
# @param key [Key]
|
38
|
+
def scard(*arguments)
|
39
|
+
call("SCARD", *arguments)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Subtract multiple sets. O(N) where N is the total number of elements in all given sets.
|
43
|
+
# @see https://redis.io/commands/sdiff
|
44
|
+
# @param key [Key]
|
45
|
+
def sdiff(*arguments)
|
46
|
+
call("SDIFF", *arguments)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Subtract multiple sets and store the resulting set in a key. O(N) where N is the total number of elements in all given sets.
|
50
|
+
# @see https://redis.io/commands/sdiffstore
|
51
|
+
# @param destination [Key]
|
52
|
+
# @param key [Key]
|
53
|
+
def sdiffstore(*arguments)
|
54
|
+
call("SDIFFSTORE", *arguments)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Intersect multiple sets. O(N*M) worst case where N is the cardinality of the smallest set and M is the number of sets.
|
58
|
+
# @see https://redis.io/commands/sinter
|
59
|
+
# @param key [Key]
|
60
|
+
def sinter(*arguments)
|
61
|
+
call("SINTER", *arguments)
|
62
|
+
end
|
63
|
+
|
64
|
+
# Intersect multiple sets and store the resulting set in a key. O(N*M) worst case where N is the cardinality of the smallest set and M is the number of sets.
|
65
|
+
# @see https://redis.io/commands/sinterstore
|
66
|
+
# @param destination [Key]
|
67
|
+
# @param key [Key]
|
68
|
+
def sinterstore(*arguments)
|
69
|
+
call("SINTERSTORE", *arguments)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Determine if a given value is a member of a set. O(1).
|
73
|
+
# @see https://redis.io/commands/sismember
|
74
|
+
# @param key [Key]
|
75
|
+
# @param member [String]
|
76
|
+
def sismember(*arguments)
|
77
|
+
call("SISMEMBER", *arguments)
|
78
|
+
end
|
79
|
+
|
80
|
+
# Get all the members in a set. O(N) where N is the set cardinality.
|
81
|
+
# @see https://redis.io/commands/smembers
|
82
|
+
# @param key [Key]
|
83
|
+
def smembers(*arguments)
|
84
|
+
call("SMEMBERS", *arguments)
|
85
|
+
end
|
86
|
+
|
87
|
+
# Move a member from one set to another. O(1).
|
88
|
+
# @see https://redis.io/commands/smove
|
89
|
+
# @param source [Key]
|
90
|
+
# @param destination [Key]
|
91
|
+
# @param member [String]
|
92
|
+
def smove(*arguments)
|
93
|
+
call("SMOVE", *arguments)
|
94
|
+
end
|
95
|
+
|
96
|
+
# Remove and return one or multiple random members from a set. O(1).
|
97
|
+
# @see https://redis.io/commands/spop
|
98
|
+
# @param key [Key]
|
99
|
+
# @param count [Integer]
|
100
|
+
def spop(*arguments)
|
101
|
+
call("SPOP", *arguments)
|
102
|
+
end
|
103
|
+
|
104
|
+
# Get one or multiple random members from a set. Without the count argument O(1), otherwise O(N) where N is the absolute value of the passed count.
|
105
|
+
# @see https://redis.io/commands/srandmember
|
106
|
+
# @param key [Key]
|
107
|
+
# @param count [Integer]
|
108
|
+
def srandmember(*arguments)
|
109
|
+
call("SRANDMEMBER", *arguments)
|
110
|
+
end
|
111
|
+
|
112
|
+
# Remove one or more members from a set. O(N) where N is the number of members to be removed.
|
113
|
+
# @see https://redis.io/commands/srem
|
114
|
+
# @param key [Key]
|
115
|
+
# @param member [String]
|
116
|
+
def srem(*arguments)
|
117
|
+
call("SREM", *arguments)
|
118
|
+
end
|
119
|
+
|
120
|
+
# Add multiple sets. O(N) where N is the total number of elements in all given sets.
|
121
|
+
# @see https://redis.io/commands/sunion
|
122
|
+
# @param key [Key]
|
123
|
+
def sunion(*arguments)
|
124
|
+
call("SUNION", *arguments)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Add multiple sets and store the resulting set in a key. O(N) where N is the total number of elements in all given sets.
|
128
|
+
# @see https://redis.io/commands/sunionstore
|
129
|
+
# @param destination [Key]
|
130
|
+
# @param key [Key]
|
131
|
+
def sunionstore(*arguments)
|
132
|
+
call("SUNIONSTORE", *arguments)
|
133
|
+
end
|
134
|
+
|
135
|
+
# Incrementally iterate Set elements. O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection..
|
136
|
+
# @see https://redis.io/commands/sscan
|
137
|
+
# @param key [Key]
|
138
|
+
# @param cursor [Integer]
|
139
|
+
def sscan(*arguments)
|
140
|
+
call("SSCAN", *arguments)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
3
4
|
# Copyright, 2020, by Dimitry Chopey.
|
4
|
-
# Copyright, 2020, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
5
5
|
#
|
6
6
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
7
|
# of this software and associated documentation files (the "Software"), to deal
|
@@ -25,6 +25,22 @@ module Protocol
|
|
25
25
|
module Redis
|
26
26
|
module Methods
|
27
27
|
module SortedSets
|
28
|
+
# Remove and return the member with the lowest score from one or more sorted sets, or block until one is available. O(log(N)) with N being the number of elements in the sorted set.
|
29
|
+
# @see https://redis.io/commands/bzpopmin
|
30
|
+
# @param key [Key]
|
31
|
+
# @param timeout [Integer]
|
32
|
+
def bzpopmin(*keys, timeout: 0)
|
33
|
+
call("BZPOPMIN", *keys, timeout)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Remove and return the member with the highest score from one or more sorted sets, or block until one is available. O(log(N)) with N being the number of elements in the sorted set.
|
37
|
+
# @see https://redis.io/commands/bzpopmax
|
38
|
+
# @param key [Key]
|
39
|
+
# @param timeout [Integer]
|
40
|
+
def bzpopmax(*keys, timeout: 0)
|
41
|
+
call("BZPOPMAX", *keys, timeout: 0)
|
42
|
+
end
|
43
|
+
|
28
44
|
# Add one or more members to a sorted set, or update its score if it already exists. O(log(N)) for each item added, where N is the number of elements in the sorted set.
|
29
45
|
# @see https://redis.io/commands/zadd
|
30
46
|
# @param key [Key]
|
@@ -41,20 +57,95 @@ module Protocol
|
|
41
57
|
arguments = ["ZADD", key]
|
42
58
|
|
43
59
|
if update == true
|
44
|
-
arguments
|
60
|
+
arguments.push("XX")
|
45
61
|
elsif update == false
|
46
|
-
arguments
|
62
|
+
arguments.push("NX")
|
47
63
|
end
|
48
64
|
|
49
|
-
arguments
|
50
|
-
arguments
|
65
|
+
arguments.push("CH") if change
|
66
|
+
arguments.push("INCR") if increment
|
51
67
|
|
52
|
-
arguments
|
53
|
-
arguments.
|
68
|
+
arguments.push(score, member)
|
69
|
+
arguments.push(*others)
|
54
70
|
|
55
71
|
call(*arguments)
|
56
72
|
end
|
57
|
-
|
73
|
+
|
74
|
+
# Get the number of members in a sorted set. O(1).
|
75
|
+
# @see https://redis.io/commands/zcard
|
76
|
+
# @param key [Key]
|
77
|
+
def zcard(key)
|
78
|
+
call("ZCARD", key)
|
79
|
+
end
|
80
|
+
|
81
|
+
# Count the members in a sorted set with scores within the given values. O(log(N)) with N being the number of elements in the sorted set.
|
82
|
+
# @see https://redis.io/commands/zcount
|
83
|
+
# @param key [Key]
|
84
|
+
# @param min [Double]
|
85
|
+
# @param max [Double]
|
86
|
+
def zcount(key, min, max)
|
87
|
+
call("ZCOUNT", key, min, max)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Increment the score of a member in a sorted set. O(log(N)) where N is the number of elements in the sorted set.
|
91
|
+
# @see https://redis.io/commands/zincrby
|
92
|
+
# @param key [Key]
|
93
|
+
# @param increment [Integer]
|
94
|
+
# @param member [String]
|
95
|
+
def zincrby(key, increment, member)
|
96
|
+
call("ZINCRBY", key, amount, member)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Intersect multiple sorted sets and store the resulting sorted set in a new key. O(N*K)+O(M*log(M)) worst case with N being the smallest input sorted set, K being the number of input sorted sets and M being the number of elements in the resulting sorted set.
|
100
|
+
# @see https://redis.io/commands/zinterstore
|
101
|
+
# @param destination [Key]
|
102
|
+
# @param keys [Array<Key>]
|
103
|
+
# @param weights [Array<Integer>]
|
104
|
+
# @param aggregate [Enum] one of sum, min, max.
|
105
|
+
def zinterstore(destination, keys, weights = nil, aggregate: nil)
|
106
|
+
arguments = []
|
107
|
+
|
108
|
+
if weights
|
109
|
+
if weights.size != keys.size
|
110
|
+
raise ArgumentError, "#{weights.size} weights given for #{keys.size} keys!"
|
111
|
+
end
|
112
|
+
|
113
|
+
arguments.push("WEIGHTS")
|
114
|
+
arguments.concat(weights)
|
115
|
+
end
|
116
|
+
|
117
|
+
if aggregate
|
118
|
+
arguments.push("AGGREGATE", aggregate)
|
119
|
+
end
|
120
|
+
|
121
|
+
call("ZINTERSTORE", destination, keys.size, *keys, *arguments)
|
122
|
+
end
|
123
|
+
|
124
|
+
# Count the number of members in a sorted set between a given lexicographical range. O(log(N)) with N being the number of elements in the sorted set.
|
125
|
+
# @see https://redis.io/commands/zlexcount
|
126
|
+
# @param key [Key]
|
127
|
+
# @param min [String]
|
128
|
+
# @param max [String]
|
129
|
+
def zlexcount(key, min, max)
|
130
|
+
call("ZLEXCOUNT", key, min, max)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Remove and return members with the highest scores in a sorted set. O(log(N)*M) with N being the number of elements in the sorted set, and M being the number of elements popped.
|
134
|
+
# @see https://redis.io/commands/zpopmax
|
135
|
+
# @param key [Key]
|
136
|
+
# @param count [Integer]
|
137
|
+
def zpopmax(key, count = 1)
|
138
|
+
call("ZPOPMAX", key, count)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Remove and return members with the lowest scores in a sorted set. O(log(N)*M) with N being the number of elements in the sorted set, and M being the number of elements popped.
|
142
|
+
# @see https://redis.io/commands/zpopmin
|
143
|
+
# @param key [Key]
|
144
|
+
# @param count [Integer]
|
145
|
+
def zpopmin(key, count = 1)
|
146
|
+
call("ZPOPMIN", key, count = 1)
|
147
|
+
end
|
148
|
+
|
58
149
|
# Return a range of members in a sorted set, by index. O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements returned.
|
59
150
|
# @see https://redis.io/commands/zrange
|
60
151
|
# @param key [Key]
|
@@ -64,11 +155,65 @@ module Protocol
|
|
64
155
|
def zrange(key, start, stop, with_scores: false)
|
65
156
|
arguments = [start, stop]
|
66
157
|
|
67
|
-
arguments
|
158
|
+
arguments.push("WITHSCORES") if with_scores
|
68
159
|
|
69
160
|
call("ZRANGE", key, *arguments)
|
70
161
|
end
|
71
162
|
|
163
|
+
# Return a range of members in a sorted set, by lexicographical range. O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)).
|
164
|
+
# @see https://redis.io/commands/zrangebylex
|
165
|
+
# @param key [Key]
|
166
|
+
# @param min [String]
|
167
|
+
# @param max [String]
|
168
|
+
# @param limit [Tuple<offset, count>] Limit the results to the specified `offset` and `count` items.
|
169
|
+
def zrangebylex(key, min, max, limit: nil)
|
170
|
+
if limit
|
171
|
+
arguments = ["LIMIT", *limit]
|
172
|
+
end
|
173
|
+
|
174
|
+
call("ZRANGEBYLEX", key, min, max, *arguments)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Return a range of members in a sorted set, by lexicographical range, ordered from higher to lower strings. O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)).
|
178
|
+
# @see https://redis.io/commands/zrevrangebylex
|
179
|
+
# @param key [Key]
|
180
|
+
# @param max [String]
|
181
|
+
# @param min [String]
|
182
|
+
def zrevrangebylex(key, min, max, limit: nil)
|
183
|
+
if limit
|
184
|
+
arguments = ["LIMIT", *limit]
|
185
|
+
end
|
186
|
+
|
187
|
+
call("ZREVRANGEBYLEX", key, min, max, *arguments)
|
188
|
+
end
|
189
|
+
|
190
|
+
# Return a range of members in a sorted set, by score. O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)).
|
191
|
+
# @see https://redis.io/commands/zrangebyscore
|
192
|
+
# @param key [Key]
|
193
|
+
# @param min [Integer]
|
194
|
+
# @param max [Integer]
|
195
|
+
# @param with_scores [Boolean] Return the scores of the elements together with the elements.
|
196
|
+
# @param limit [Tuple<offset, count>] Limit the results to the specified `offset` and `count` items.
|
197
|
+
#
|
198
|
+
# @example Retrieve the first 10 members with score `>= 0` and `<= 100`
|
199
|
+
# redis.zrangebyscore("zset", "0", "100", limit: [0, 10])
|
200
|
+
def zrangebyscore(key, min, max, with_scores: false, limit: nil)
|
201
|
+
arguments = [min, max]
|
202
|
+
|
203
|
+
arguments.push('WITHSCORES') if with_scores
|
204
|
+
arguments.push('LIMIT', *limit) if limit
|
205
|
+
|
206
|
+
call('ZRANGEBYSCORE', key, *arguments)
|
207
|
+
end
|
208
|
+
|
209
|
+
# Determine the index of a member in a sorted set. O(log(N)).
|
210
|
+
# @see https://redis.io/commands/zrank
|
211
|
+
# @param key [Key]
|
212
|
+
# @param member [String]
|
213
|
+
def zrank(key, member)
|
214
|
+
call("ZRANK", key, member)
|
215
|
+
end
|
216
|
+
|
72
217
|
# Remove one or more members from a sorted set. O(M*log(N)) with N being the number of elements in the sorted set and M the number of elements to be removed.
|
73
218
|
# @see https://redis.io/commands/zrem
|
74
219
|
# @param key [Key]
|
@@ -76,6 +221,105 @@ module Protocol
|
|
76
221
|
def zrem(key, member)
|
77
222
|
call("ZREM", key, member)
|
78
223
|
end
|
224
|
+
|
225
|
+
# Remove all members in a sorted set between the given lexicographical range. O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements removed by the operation.
|
226
|
+
# @see https://redis.io/commands/zremrangebylex
|
227
|
+
# @param key [Key]
|
228
|
+
# @param min [String]
|
229
|
+
# @param max [String]
|
230
|
+
def zremrangebylex(key, min, max)
|
231
|
+
call("ZREMRANGEBYLEX", key, min, max)
|
232
|
+
end
|
233
|
+
|
234
|
+
# Remove all members in a sorted set within the given indexes. O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements removed by the operation.
|
235
|
+
# @see https://redis.io/commands/zremrangebyrank
|
236
|
+
# @param key [Key]
|
237
|
+
# @param start [Integer]
|
238
|
+
# @param stop [Integer]
|
239
|
+
def zremrangebyrank(key, start, stop)
|
240
|
+
call("ZREMRANGEBYRANK", key, start, stop)
|
241
|
+
end
|
242
|
+
|
243
|
+
# Remove all members in a sorted set within the given scores. O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements removed by the operation.
|
244
|
+
# @see https://redis.io/commands/zremrangebyscore
|
245
|
+
# @param key [Key]
|
246
|
+
# @param min [Double]
|
247
|
+
# @param max [Double]
|
248
|
+
def zremrangebyscore(key, min, max)
|
249
|
+
call("ZREMRANGEBYSCORE", key, min, max)
|
250
|
+
end
|
251
|
+
|
252
|
+
# Return a range of members in a sorted set, by index, with scores ordered from high to low. O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements returned.
|
253
|
+
# @see https://redis.io/commands/zrevrange
|
254
|
+
# @param key [Key]
|
255
|
+
# @param start [Integer]
|
256
|
+
# @param stop [Integer]
|
257
|
+
# @param withscores [Enum]
|
258
|
+
def zrevrange(key, min, max, with_scores: false)
|
259
|
+
arguments = [min, max]
|
260
|
+
|
261
|
+
arguments.push('WITHSCORES') if with_scores
|
262
|
+
|
263
|
+
call("ZREVRANGE", key, *arguments)
|
264
|
+
end
|
265
|
+
|
266
|
+
# Return a range of members in a sorted set, by score, with scores ordered from high to low. O(log(N)+M) with N being the number of elements in the sorted set and M the number of elements being returned. If M is constant (e.g. always asking for the first 10 elements with LIMIT), you can consider it O(log(N)).
|
267
|
+
# @see https://redis.io/commands/zrevrangebyscore
|
268
|
+
# @param key [Key]
|
269
|
+
# @param max [Double]
|
270
|
+
# @param min [Double]
|
271
|
+
# @param withscores [Enum]
|
272
|
+
def zrevrangebyscore(key, min, max, with_scores: false, limit: nil)
|
273
|
+
arguments = [min, max]
|
274
|
+
|
275
|
+
arguments.push('WITHSCORES') if with_scores
|
276
|
+
arguments.push('LIMIT', *limit) if limit
|
277
|
+
|
278
|
+
call("ZREVRANGEBYSCORE", key, *arguments)
|
279
|
+
end
|
280
|
+
|
281
|
+
# Determine the index of a member in a sorted set, with scores ordered from high to low. O(log(N)).
|
282
|
+
# @see https://redis.io/commands/zrevrank
|
283
|
+
# @param key [Key]
|
284
|
+
# @param member [String]
|
285
|
+
def zrevrank(key, member)
|
286
|
+
call("ZREVRANK", key, member)
|
287
|
+
end
|
288
|
+
|
289
|
+
# Get the score associated with the given member in a sorted set. O(1).
|
290
|
+
# @see https://redis.io/commands/zscore
|
291
|
+
# @param key [Key]
|
292
|
+
# @param member [String]
|
293
|
+
def zscore(key, member)
|
294
|
+
call("ZSCORE", key, member)
|
295
|
+
end
|
296
|
+
|
297
|
+
# Add multiple sorted sets and store the resulting sorted set in a new key. O(N)+O(M log(M)) with N being the sum of the sizes of the input sorted sets, and M being the number of elements in the resulting sorted set.
|
298
|
+
# @see https://redis.io/commands/zunionstore
|
299
|
+
# @param destination [Key]
|
300
|
+
# @param numkeys [Integer]
|
301
|
+
# @param key [Key]
|
302
|
+
def zunionstore(*arguments)
|
303
|
+
call("ZUNIONSTORE", *arguments)
|
304
|
+
end
|
305
|
+
|
306
|
+
# Incrementally iterate sorted sets elements and associated scores. O(1) for every call. O(N) for a complete iteration, including enough command calls for the cursor to return back to 0. N is the number of elements inside the collection..
|
307
|
+
# @see https://redis.io/commands/zscan
|
308
|
+
# @param key [Key]
|
309
|
+
# @param cursor [Integer]
|
310
|
+
def zscan(key, cursor = 0, match: nil, count: nil)
|
311
|
+
arguments = [key, cursor]
|
312
|
+
|
313
|
+
if match
|
314
|
+
arguments.push("MATCH", match)
|
315
|
+
end
|
316
|
+
|
317
|
+
if count
|
318
|
+
arguments.push("COUNT", count)
|
319
|
+
end
|
320
|
+
|
321
|
+
call("ZSCAN", *arguments)
|
322
|
+
end
|
79
323
|
end
|
80
324
|
end
|
81
325
|
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
# of this software and associated documentation files (the "Software"), to deal
|
7
|
+
# in the Software without restriction, including without limitation the rights
|
8
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
# copies of the Software, and to permit persons to whom the Software is
|
10
|
+
# furnished to do so, subject to the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be included in
|
13
|
+
# all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
# THE SOFTWARE.
|
22
|
+
|
23
|
+
module Protocol
|
24
|
+
module Redis
|
25
|
+
module Methods
|
26
|
+
module Streams
|
27
|
+
# Get information on streams and consumer groups. O(N) with N being the number of returned items for the subcommands CONSUMERS and GROUPS. The STREAM subcommand is O(log N) with N being the number of items in the stream.
|
28
|
+
# @see https://redis.io/commands/xinfo
|
29
|
+
# @param help [Enum]
|
30
|
+
def xinfo(*arguments)
|
31
|
+
call("XINFO", *arguments)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Appends a new entry to a stream. O(1).
|
35
|
+
# @see https://redis.io/commands/xadd
|
36
|
+
# @param key [Key]
|
37
|
+
# @param ID [String]
|
38
|
+
def xadd(*arguments)
|
39
|
+
call("XADD", *arguments)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Trims the stream to (approximately if '~' is passed) a certain size. O(N), with N being the number of evicted entries. Constant times are very small however, since entries are organized in macro nodes containing multiple entries that can be released with a single deallocation.
|
43
|
+
# @see https://redis.io/commands/xtrim
|
44
|
+
# @param key [Key]
|
45
|
+
# @param strategy [Enum]
|
46
|
+
# @param approx [Enum]
|
47
|
+
# @param count [Integer]
|
48
|
+
def xtrim(*arguments)
|
49
|
+
call("XTRIM", *arguments)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Removes the specified entries from the stream. Returns the number of items actually deleted, that may be different from the number of IDs passed in case certain IDs do not exist. O(1) for each single item to delete in the stream, regardless of the stream size.
|
53
|
+
# @see https://redis.io/commands/xdel
|
54
|
+
# @param key [Key]
|
55
|
+
# @param ID [String]
|
56
|
+
def xdel(*arguments)
|
57
|
+
call("XDEL", *arguments)
|
58
|
+
end
|
59
|
+
|
60
|
+
# Return a range of elements in a stream, with IDs matching the specified IDs interval. O(N) with N being the number of elements being returned. If N is constant (e.g. always asking for the first 10 elements with COUNT), you can consider it O(1).
|
61
|
+
# @see https://redis.io/commands/xrange
|
62
|
+
# @param key [Key]
|
63
|
+
# @param start [String]
|
64
|
+
# @param end [String]
|
65
|
+
def xrange(*arguments)
|
66
|
+
call("XRANGE", *arguments)
|
67
|
+
end
|
68
|
+
|
69
|
+
# Return a range of elements in a stream, with IDs matching the specified IDs interval, in reverse order (from greater to smaller IDs) compared to XRANGE. O(N) with N being the number of elements returned. If N is constant (e.g. always asking for the first 10 elements with COUNT), you can consider it O(1).
|
70
|
+
# @see https://redis.io/commands/xrevrange
|
71
|
+
# @param key [Key]
|
72
|
+
# @param end [String]
|
73
|
+
# @param start [String]
|
74
|
+
def xrevrange(*arguments)
|
75
|
+
call("XREVRANGE", *arguments)
|
76
|
+
end
|
77
|
+
|
78
|
+
# Return the number of entires in a stream. O(1).
|
79
|
+
# @see https://redis.io/commands/xlen
|
80
|
+
# @param key [Key]
|
81
|
+
def xlen(*arguments)
|
82
|
+
call("XLEN", *arguments)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Return never seen elements in multiple streams, with IDs greater than the ones reported by the caller for each stream. Can block. For each stream mentioned: O(N) with N being the number of elements being returned, it means that XREAD-ing with a fixed COUNT is O(1). Note that when the BLOCK option is used, XADD will pay O(M) time in order to serve the M clients blocked on the stream getting new data.
|
86
|
+
# @see https://redis.io/commands/xread
|
87
|
+
# @param streams [Enum]
|
88
|
+
# @param key [Key]
|
89
|
+
# @param id [String]
|
90
|
+
def xread(*arguments)
|
91
|
+
call("XREAD", *arguments)
|
92
|
+
end
|
93
|
+
|
94
|
+
# Create, destroy, and manage consumer groups. O(1) for all the subcommands, with the exception of the DESTROY subcommand which takes an additional O(M) time in order to delete the M entries inside the consumer group pending entries list (PEL).
|
95
|
+
# @see https://redis.io/commands/xgroup
|
96
|
+
def xgroup(*arguments)
|
97
|
+
call("XGROUP", *arguments)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Return new entries from a stream using a consumer group, or access the history of the pending entries for a given consumer. Can block. For each stream mentioned: O(M) with M being the number of elements returned. If M is constant (e.g. always asking for the first 10 elements with COUNT), you can consider it O(1). On the other side when XREADGROUP blocks, XADD will pay the O(N) time in order to serve the N clients blocked on the stream getting new data.
|
101
|
+
# @see https://redis.io/commands/xreadgroup
|
102
|
+
# @param noack [Enum]
|
103
|
+
# @param streams [Enum]
|
104
|
+
# @param key [Key]
|
105
|
+
# @param ID [String]
|
106
|
+
def xreadgroup(*arguments)
|
107
|
+
call("XREADGROUP", *arguments)
|
108
|
+
end
|
109
|
+
|
110
|
+
# Marks a pending message as correctly processed, effectively removing it from the pending entries list of the consumer group. Return value of the command is the number of messages successfully acknowledged, that is, the IDs we were actually able to resolve in the PEL. O(1) for each message ID processed.
|
111
|
+
# @see https://redis.io/commands/xack
|
112
|
+
# @param key [Key]
|
113
|
+
# @param group [String]
|
114
|
+
# @param ID [String]
|
115
|
+
def xack(*arguments)
|
116
|
+
call("XACK", *arguments)
|
117
|
+
end
|
118
|
+
|
119
|
+
# Changes (or acquires) ownership of a message in a consumer group, as if the message was delivered to the specified consumer. O(log N) with N being the number of messages in the PEL of the consumer group.
|
120
|
+
# @see https://redis.io/commands/xclaim
|
121
|
+
# @param key [Key]
|
122
|
+
# @param group [String]
|
123
|
+
# @param consumer [String]
|
124
|
+
# @param min-idle-time [String]
|
125
|
+
# @param ID [String]
|
126
|
+
def xclaim(*arguments)
|
127
|
+
call("XCLAIM", *arguments)
|
128
|
+
end
|
129
|
+
|
130
|
+
# Return information and entries from a stream consumer group pending entries list, that are messages fetched but never acknowledged. O(N) with N being the number of elements returned, so asking for a small fixed number of entries per call is O(1). When the command returns just the summary it runs in O(1) time assuming the list of consumers is small, otherwise there is additional O(N) time needed to iterate every consumer.
|
131
|
+
# @see https://redis.io/commands/xpending
|
132
|
+
# @param key [Key]
|
133
|
+
# @param group [String]
|
134
|
+
# @param consumer [String]
|
135
|
+
def xpending(*arguments)
|
136
|
+
call("XPENDING", *arguments)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/protocol-redis.gemspec
CHANGED
@@ -2,19 +2,18 @@
|
|
2
2
|
require_relative 'lib/protocol/redis/version'
|
3
3
|
|
4
4
|
Gem::Specification.new do |spec|
|
5
|
-
spec.name
|
6
|
-
spec.version
|
7
|
-
spec.authors
|
8
|
-
spec.email
|
9
|
-
|
10
|
-
spec.summary
|
11
|
-
spec.homepage
|
12
|
-
|
13
|
-
spec.files
|
5
|
+
spec.name = "protocol-redis"
|
6
|
+
spec.version = Protocol::Redis::VERSION
|
7
|
+
spec.authors = ["Samuel Williams", "Huba Nagy"]
|
8
|
+
spec.email = ["samuel.williams@oriontransfer.co.nz", "12huba@gmail.com"]
|
9
|
+
|
10
|
+
spec.summary = "A transport agnostic RESP protocol client/server."
|
11
|
+
spec.homepage = "https://github.com/socketry/protocol-redis"
|
12
|
+
|
13
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
14
14
|
f.match(%r{^(test|spec|features)/})
|
15
15
|
end
|
16
16
|
|
17
|
-
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
17
|
spec.require_paths = ["lib"]
|
19
18
|
|
20
19
|
spec.add_development_dependency "async-http"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protocol-redis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Samuel Williams
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2020-02-
|
12
|
+
date: 2020-02-22 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: async-http
|
@@ -118,9 +118,9 @@ extensions: []
|
|
118
118
|
extra_rdoc_files: []
|
119
119
|
files:
|
120
120
|
- ".editorconfig"
|
121
|
+
- ".github/workflows/development.yml"
|
121
122
|
- ".gitignore"
|
122
123
|
- ".rspec"
|
123
|
-
- ".travis.yml"
|
124
124
|
- Gemfile
|
125
125
|
- README.md
|
126
126
|
- Rakefile
|
@@ -135,8 +135,11 @@ files:
|
|
135
135
|
- lib/protocol/redis/methods/geospatial.rb
|
136
136
|
- lib/protocol/redis/methods/hashes.rb
|
137
137
|
- lib/protocol/redis/methods/lists.rb
|
138
|
+
- lib/protocol/redis/methods/scripting.rb
|
138
139
|
- lib/protocol/redis/methods/server.rb
|
140
|
+
- lib/protocol/redis/methods/sets.rb
|
139
141
|
- lib/protocol/redis/methods/sorted_sets.rb
|
142
|
+
- lib/protocol/redis/methods/streams.rb
|
140
143
|
- lib/protocol/redis/methods/strings.rb
|
141
144
|
- lib/protocol/redis/version.rb
|
142
145
|
- protocol-redis.gemspec
|
@@ -160,8 +163,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
160
163
|
- !ruby/object:Gem::Version
|
161
164
|
version: '0'
|
162
165
|
requirements: []
|
163
|
-
rubygems_version: 3.
|
166
|
+
rubygems_version: 3.1.2
|
164
167
|
signing_key:
|
165
168
|
specification_version: 4
|
166
|
-
summary: A RESP protocol client/server
|
169
|
+
summary: A transport agnostic RESP protocol client/server.
|
167
170
|
test_files: []
|
data/.travis.yml
DELETED
@@ -1,22 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
dist: xenial
|
3
|
-
cache: bundler
|
4
|
-
|
5
|
-
services:
|
6
|
-
- redis-server
|
7
|
-
|
8
|
-
matrix:
|
9
|
-
include:
|
10
|
-
- rvm: 2.5
|
11
|
-
- rvm: 2.6
|
12
|
-
- rvm: 2.7
|
13
|
-
- rvm: 2.6
|
14
|
-
env: COVERAGE=BriefSummary,Coveralls
|
15
|
-
- rvm: ruby-head
|
16
|
-
- rvm: truffleruby
|
17
|
-
- rvm: jruby-head
|
18
|
-
env: JRUBY_OPTS="--debug -X+O"
|
19
|
-
allow_failures:
|
20
|
-
- rvm: ruby-head
|
21
|
-
- rvm: truffleruby
|
22
|
-
- rvm: jruby-head
|