redis 4.5.0 → 4.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +65 -0
- data/README.md +25 -10
- data/lib/redis/client.rb +23 -12
- data/lib/redis/cluster/command.rb +4 -6
- data/lib/redis/cluster/command_loader.rb +5 -5
- data/lib/redis/cluster/node.rb +12 -0
- data/lib/redis/cluster/node_loader.rb +8 -11
- data/lib/redis/cluster/option.rb +10 -3
- data/lib/redis/cluster/slot_loader.rb +9 -12
- data/lib/redis/cluster.rb +24 -0
- data/lib/redis/commands/bitmaps.rb +63 -0
- data/lib/redis/commands/cluster.rb +45 -0
- data/lib/redis/commands/connection.rb +58 -0
- data/lib/redis/commands/geo.rb +84 -0
- data/lib/redis/commands/hashes.rb +251 -0
- data/lib/redis/commands/hyper_log_log.rb +37 -0
- data/lib/redis/commands/keys.rb +411 -0
- data/lib/redis/commands/lists.rb +289 -0
- data/lib/redis/commands/pubsub.rb +72 -0
- data/lib/redis/commands/scripting.rb +114 -0
- data/lib/redis/commands/server.rb +188 -0
- data/lib/redis/commands/sets.rb +207 -0
- data/lib/redis/commands/sorted_sets.rb +812 -0
- data/lib/redis/commands/streams.rb +382 -0
- data/lib/redis/commands/strings.rb +313 -0
- data/lib/redis/commands/transactions.rb +139 -0
- data/lib/redis/commands.rb +242 -0
- data/lib/redis/connection/hiredis.rb +3 -4
- data/lib/redis/connection/ruby.rb +14 -28
- data/lib/redis/connection/synchrony.rb +10 -8
- data/lib/redis/connection.rb +1 -1
- data/lib/redis/distributed.rb +46 -9
- data/lib/redis/errors.rb +9 -0
- data/lib/redis/pipeline.rb +128 -3
- data/lib/redis/version.rb +1 -1
- data/lib/redis.rb +137 -3673
- metadata +21 -4
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Redis
|
4
|
+
module Commands
|
5
|
+
module Pubsub
|
6
|
+
# Post a message to a channel.
|
7
|
+
def publish(channel, message)
|
8
|
+
send_command([:publish, channel, message])
|
9
|
+
end
|
10
|
+
|
11
|
+
def subscribed?
|
12
|
+
synchronize do |client|
|
13
|
+
client.is_a? SubscribedClient
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Listen for messages published to the given channels.
|
18
|
+
def subscribe(*channels, &block)
|
19
|
+
synchronize do |_client|
|
20
|
+
_subscription(:subscribe, 0, channels, block)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Listen for messages published to the given channels. Throw a timeout error
|
25
|
+
# if there is no messages for a timeout period.
|
26
|
+
def subscribe_with_timeout(timeout, *channels, &block)
|
27
|
+
synchronize do |_client|
|
28
|
+
_subscription(:subscribe_with_timeout, timeout, channels, block)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Stop listening for messages posted to the given channels.
|
33
|
+
def unsubscribe(*channels)
|
34
|
+
synchronize do |client|
|
35
|
+
raise "Can't unsubscribe if not subscribed." unless subscribed?
|
36
|
+
|
37
|
+
client.unsubscribe(*channels)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Listen for messages published to channels matching the given patterns.
|
42
|
+
def psubscribe(*channels, &block)
|
43
|
+
synchronize do |_client|
|
44
|
+
_subscription(:psubscribe, 0, channels, block)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Listen for messages published to channels matching the given patterns.
|
49
|
+
# Throw a timeout error if there is no messages for a timeout period.
|
50
|
+
def psubscribe_with_timeout(timeout, *channels, &block)
|
51
|
+
synchronize do |_client|
|
52
|
+
_subscription(:psubscribe_with_timeout, timeout, channels, block)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Stop listening for messages posted to channels matching the given patterns.
|
57
|
+
def punsubscribe(*channels)
|
58
|
+
synchronize do |client|
|
59
|
+
raise "Can't unsubscribe if not subscribed." unless subscribed?
|
60
|
+
|
61
|
+
client.punsubscribe(*channels)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Inspect the state of the Pub/Sub subsystem.
|
66
|
+
# Possible subcommands: channels, numsub, numpat.
|
67
|
+
def pubsub(subcommand, *args)
|
68
|
+
send_command([:pubsub, subcommand] + args)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Redis
|
4
|
+
module Commands
|
5
|
+
module Scripting
|
6
|
+
# Control remote script registry.
|
7
|
+
#
|
8
|
+
# @example Load a script
|
9
|
+
# sha = redis.script(:load, "return 1")
|
10
|
+
# # => <sha of this script>
|
11
|
+
# @example Check if a script exists
|
12
|
+
# redis.script(:exists, sha)
|
13
|
+
# # => true
|
14
|
+
# @example Check if multiple scripts exist
|
15
|
+
# redis.script(:exists, [sha, other_sha])
|
16
|
+
# # => [true, false]
|
17
|
+
# @example Flush the script registry
|
18
|
+
# redis.script(:flush)
|
19
|
+
# # => "OK"
|
20
|
+
# @example Kill a running script
|
21
|
+
# redis.script(:kill)
|
22
|
+
# # => "OK"
|
23
|
+
#
|
24
|
+
# @param [String] subcommand e.g. `exists`, `flush`, `load`, `kill`
|
25
|
+
# @param [Array<String>] args depends on subcommand
|
26
|
+
# @return [String, Boolean, Array<Boolean>, ...] depends on subcommand
|
27
|
+
#
|
28
|
+
# @see #eval
|
29
|
+
# @see #evalsha
|
30
|
+
def script(subcommand, *args)
|
31
|
+
subcommand = subcommand.to_s.downcase
|
32
|
+
|
33
|
+
if subcommand == "exists"
|
34
|
+
arg = args.first
|
35
|
+
|
36
|
+
send_command([:script, :exists, arg]) do |reply|
|
37
|
+
reply = reply.map { |r| Boolify.call(r) }
|
38
|
+
|
39
|
+
if arg.is_a?(Array)
|
40
|
+
reply
|
41
|
+
else
|
42
|
+
reply.first
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
send_command([:script, subcommand] + args)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Evaluate Lua script.
|
51
|
+
#
|
52
|
+
# @example EVAL without KEYS nor ARGV
|
53
|
+
# redis.eval("return 1")
|
54
|
+
# # => 1
|
55
|
+
# @example EVAL with KEYS and ARGV as array arguments
|
56
|
+
# redis.eval("return { KEYS, ARGV }", ["k1", "k2"], ["a1", "a2"])
|
57
|
+
# # => [["k1", "k2"], ["a1", "a2"]]
|
58
|
+
# @example EVAL with KEYS and ARGV in a hash argument
|
59
|
+
# redis.eval("return { KEYS, ARGV }", :keys => ["k1", "k2"], :argv => ["a1", "a2"])
|
60
|
+
# # => [["k1", "k2"], ["a1", "a2"]]
|
61
|
+
#
|
62
|
+
# @param [Array<String>] keys optional array with keys to pass to the script
|
63
|
+
# @param [Array<String>] argv optional array with arguments to pass to the script
|
64
|
+
# @param [Hash] options
|
65
|
+
# - `:keys => Array<String>`: optional array with keys to pass to the script
|
66
|
+
# - `:argv => Array<String>`: optional array with arguments to pass to the script
|
67
|
+
# @return depends on the script
|
68
|
+
#
|
69
|
+
# @see #script
|
70
|
+
# @see #evalsha
|
71
|
+
def eval(*args)
|
72
|
+
_eval(:eval, args)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Evaluate Lua script by its SHA.
|
76
|
+
#
|
77
|
+
# @example EVALSHA without KEYS nor ARGV
|
78
|
+
# redis.evalsha(sha)
|
79
|
+
# # => <depends on script>
|
80
|
+
# @example EVALSHA with KEYS and ARGV as array arguments
|
81
|
+
# redis.evalsha(sha, ["k1", "k2"], ["a1", "a2"])
|
82
|
+
# # => <depends on script>
|
83
|
+
# @example EVALSHA with KEYS and ARGV in a hash argument
|
84
|
+
# redis.evalsha(sha, :keys => ["k1", "k2"], :argv => ["a1", "a2"])
|
85
|
+
# # => <depends on script>
|
86
|
+
#
|
87
|
+
# @param [Array<String>] keys optional array with keys to pass to the script
|
88
|
+
# @param [Array<String>] argv optional array with arguments to pass to the script
|
89
|
+
# @param [Hash] options
|
90
|
+
# - `:keys => Array<String>`: optional array with keys to pass to the script
|
91
|
+
# - `:argv => Array<String>`: optional array with arguments to pass to the script
|
92
|
+
# @return depends on the script
|
93
|
+
#
|
94
|
+
# @see #script
|
95
|
+
# @see #eval
|
96
|
+
def evalsha(*args)
|
97
|
+
_eval(:evalsha, args)
|
98
|
+
end
|
99
|
+
|
100
|
+
private
|
101
|
+
|
102
|
+
def _eval(cmd, args)
|
103
|
+
script = args.shift
|
104
|
+
options = args.pop if args.last.is_a?(Hash)
|
105
|
+
options ||= {}
|
106
|
+
|
107
|
+
keys = args.shift || options[:keys] || []
|
108
|
+
argv = args.shift || options[:argv] || []
|
109
|
+
|
110
|
+
send_command([cmd, script, keys.length] + keys + argv)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -0,0 +1,188 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Redis
|
4
|
+
module Commands
|
5
|
+
module Server
|
6
|
+
# Asynchronously rewrite the append-only file.
|
7
|
+
#
|
8
|
+
# @return [String] `OK`
|
9
|
+
def bgrewriteaof
|
10
|
+
send_command([:bgrewriteaof])
|
11
|
+
end
|
12
|
+
|
13
|
+
# Asynchronously save the dataset to disk.
|
14
|
+
#
|
15
|
+
# @return [String] `OK`
|
16
|
+
def bgsave
|
17
|
+
send_command([:bgsave])
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get or set server configuration parameters.
|
21
|
+
#
|
22
|
+
# @param [Symbol] action e.g. `:get`, `:set`, `:resetstat`
|
23
|
+
# @return [String, Hash] string reply, or hash when retrieving more than one
|
24
|
+
# property with `CONFIG GET`
|
25
|
+
def config(action, *args)
|
26
|
+
send_command([:config, action] + args) do |reply|
|
27
|
+
if reply.is_a?(Array) && action == :get
|
28
|
+
Hashify.call(reply)
|
29
|
+
else
|
30
|
+
reply
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Manage client connections.
|
36
|
+
#
|
37
|
+
# @param [String, Symbol] subcommand e.g. `kill`, `list`, `getname`, `setname`
|
38
|
+
# @return [String, Hash] depends on subcommand
|
39
|
+
def client(subcommand = nil, *args)
|
40
|
+
send_command([:client, subcommand] + args) do |reply|
|
41
|
+
if subcommand.to_s == "list"
|
42
|
+
reply.lines.map do |line|
|
43
|
+
entries = line.chomp.split(/[ =]/)
|
44
|
+
Hash[entries.each_slice(2).to_a]
|
45
|
+
end
|
46
|
+
else
|
47
|
+
reply
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
# Return the number of keys in the selected database.
|
53
|
+
#
|
54
|
+
# @return [Integer]
|
55
|
+
def dbsize
|
56
|
+
send_command([:dbsize])
|
57
|
+
end
|
58
|
+
|
59
|
+
# Remove all keys from all databases.
|
60
|
+
#
|
61
|
+
# @param [Hash] options
|
62
|
+
# - `:async => Boolean`: async flush (default: false)
|
63
|
+
# @return [String] `OK`
|
64
|
+
def flushall(options = nil)
|
65
|
+
if options && options[:async]
|
66
|
+
send_command(%i[flushall async])
|
67
|
+
else
|
68
|
+
send_command([:flushall])
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Remove all keys from the current database.
|
73
|
+
#
|
74
|
+
# @param [Hash] options
|
75
|
+
# - `:async => Boolean`: async flush (default: false)
|
76
|
+
# @return [String] `OK`
|
77
|
+
def flushdb(options = nil)
|
78
|
+
if options && options[:async]
|
79
|
+
send_command(%i[flushdb async])
|
80
|
+
else
|
81
|
+
send_command([:flushdb])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
# Get information and statistics about the server.
|
86
|
+
#
|
87
|
+
# @param [String, Symbol] cmd e.g. "commandstats"
|
88
|
+
# @return [Hash<String, String>]
|
89
|
+
def info(cmd = nil)
|
90
|
+
send_command([:info, cmd].compact) do |reply|
|
91
|
+
if reply.is_a?(String)
|
92
|
+
reply = HashifyInfo.call(reply)
|
93
|
+
|
94
|
+
if cmd && cmd.to_s == "commandstats"
|
95
|
+
# Extract nested hashes for INFO COMMANDSTATS
|
96
|
+
reply = Hash[reply.map do |k, v|
|
97
|
+
v = v.split(",").map { |e| e.split("=") }
|
98
|
+
[k[/^cmdstat_(.*)$/, 1], Hash[v]]
|
99
|
+
end]
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
reply
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
# Get the UNIX time stamp of the last successful save to disk.
|
108
|
+
#
|
109
|
+
# @return [Integer]
|
110
|
+
def lastsave
|
111
|
+
send_command([:lastsave])
|
112
|
+
end
|
113
|
+
|
114
|
+
# Listen for all requests received by the server in real time.
|
115
|
+
#
|
116
|
+
# There is no way to interrupt this command.
|
117
|
+
#
|
118
|
+
# @yield a block to be called for every line of output
|
119
|
+
# @yieldparam [String] line timestamp and command that was executed
|
120
|
+
def monitor(&block)
|
121
|
+
synchronize do |client|
|
122
|
+
client.call_loop([:monitor], &block)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# Synchronously save the dataset to disk.
|
127
|
+
#
|
128
|
+
# @return [String]
|
129
|
+
def save
|
130
|
+
send_command([:save])
|
131
|
+
end
|
132
|
+
|
133
|
+
# Synchronously save the dataset to disk and then shut down the server.
|
134
|
+
def shutdown
|
135
|
+
synchronize do |client|
|
136
|
+
client.with_reconnect(false) do
|
137
|
+
begin
|
138
|
+
client.call([:shutdown])
|
139
|
+
rescue ConnectionError
|
140
|
+
# This means Redis has probably exited.
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
# Make the server a slave of another instance, or promote it as master.
|
148
|
+
def slaveof(host, port)
|
149
|
+
send_command([:slaveof, host, port])
|
150
|
+
end
|
151
|
+
|
152
|
+
# Interact with the slowlog (get, len, reset)
|
153
|
+
#
|
154
|
+
# @param [String] subcommand e.g. `get`, `len`, `reset`
|
155
|
+
# @param [Integer] length maximum number of entries to return
|
156
|
+
# @return [Array<String>, Integer, String] depends on subcommand
|
157
|
+
def slowlog(subcommand, length = nil)
|
158
|
+
synchronize do |client|
|
159
|
+
args = [:slowlog, subcommand]
|
160
|
+
args << length if length
|
161
|
+
client.call args
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
# Internal command used for replication.
|
166
|
+
def sync
|
167
|
+
send_command([:sync])
|
168
|
+
end
|
169
|
+
|
170
|
+
# Return the server time.
|
171
|
+
#
|
172
|
+
# @example
|
173
|
+
# r.time # => [ 1333093196, 606806 ]
|
174
|
+
#
|
175
|
+
# @return [Array<Integer>] tuple of seconds since UNIX epoch and
|
176
|
+
# microseconds in the current second
|
177
|
+
def time
|
178
|
+
send_command([:time]) do |reply|
|
179
|
+
reply&.map(&:to_i)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def debug(*args)
|
184
|
+
send_command([:debug] + args)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Redis
|
4
|
+
module Commands
|
5
|
+
module Sets
|
6
|
+
# Get the number of members in a set.
|
7
|
+
#
|
8
|
+
# @param [String] key
|
9
|
+
# @return [Integer]
|
10
|
+
def scard(key)
|
11
|
+
send_command([:scard, key])
|
12
|
+
end
|
13
|
+
|
14
|
+
# Add one or more members to a set.
|
15
|
+
#
|
16
|
+
# @param [String] key
|
17
|
+
# @param [String, Array<String>] member one member, or array of members
|
18
|
+
# @return [Boolean, Integer] `Boolean` when a single member is specified,
|
19
|
+
# holding whether or not adding the member succeeded, or `Integer` when an
|
20
|
+
# array of members is specified, holding the number of members that were
|
21
|
+
# successfully added
|
22
|
+
def sadd(key, member)
|
23
|
+
send_command([:sadd, key, member]) do |reply|
|
24
|
+
if member.is_a? Array
|
25
|
+
# Variadic: return integer
|
26
|
+
reply
|
27
|
+
else
|
28
|
+
# Single argument: return boolean
|
29
|
+
Boolify.call(reply)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Remove one or more members from a set.
|
35
|
+
#
|
36
|
+
# @param [String] key
|
37
|
+
# @param [String, Array<String>] member one member, or array of members
|
38
|
+
# @return [Boolean, Integer] `Boolean` when a single member is specified,
|
39
|
+
# holding whether or not removing the member succeeded, or `Integer` when an
|
40
|
+
# array of members is specified, holding the number of members that were
|
41
|
+
# successfully removed
|
42
|
+
def srem(key, member)
|
43
|
+
send_command([:srem, key, member]) do |reply|
|
44
|
+
if member.is_a? Array
|
45
|
+
# Variadic: return integer
|
46
|
+
reply
|
47
|
+
else
|
48
|
+
# Single argument: return boolean
|
49
|
+
Boolify.call(reply)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Remove and return one or more random member from a set.
|
55
|
+
#
|
56
|
+
# @param [String] key
|
57
|
+
# @return [String]
|
58
|
+
# @param [Integer] count
|
59
|
+
def spop(key, count = nil)
|
60
|
+
if count.nil?
|
61
|
+
send_command([:spop, key])
|
62
|
+
else
|
63
|
+
send_command([:spop, key, count])
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Get one or more random members from a set.
|
68
|
+
#
|
69
|
+
# @param [String] key
|
70
|
+
# @param [Integer] count
|
71
|
+
# @return [String]
|
72
|
+
def srandmember(key, count = nil)
|
73
|
+
if count.nil?
|
74
|
+
send_command([:srandmember, key])
|
75
|
+
else
|
76
|
+
send_command([:srandmember, key, count])
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Move a member from one set to another.
|
81
|
+
#
|
82
|
+
# @param [String] source source key
|
83
|
+
# @param [String] destination destination key
|
84
|
+
# @param [String] member member to move from `source` to `destination`
|
85
|
+
# @return [Boolean]
|
86
|
+
def smove(source, destination, member)
|
87
|
+
send_command([:smove, source, destination, member], &Boolify)
|
88
|
+
end
|
89
|
+
|
90
|
+
# Determine if a given value is a member of a set.
|
91
|
+
#
|
92
|
+
# @param [String] key
|
93
|
+
# @param [String] member
|
94
|
+
# @return [Boolean]
|
95
|
+
def sismember(key, member)
|
96
|
+
send_command([:sismember, key, member], &Boolify)
|
97
|
+
end
|
98
|
+
|
99
|
+
# Determine if multiple values are members of a set.
|
100
|
+
#
|
101
|
+
# @param [String] key
|
102
|
+
# @param [String, Array<String>] members
|
103
|
+
# @return [Array<Boolean>]
|
104
|
+
def smismember(key, *members)
|
105
|
+
send_command([:smismember, key, *members]) do |reply|
|
106
|
+
reply.map(&Boolify)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# Get all the members in a set.
|
111
|
+
#
|
112
|
+
# @param [String] key
|
113
|
+
# @return [Array<String>]
|
114
|
+
def smembers(key)
|
115
|
+
send_command([:smembers, key])
|
116
|
+
end
|
117
|
+
|
118
|
+
# Subtract multiple sets.
|
119
|
+
#
|
120
|
+
# @param [String, Array<String>] keys keys pointing to sets to subtract
|
121
|
+
# @return [Array<String>] members in the difference
|
122
|
+
def sdiff(*keys)
|
123
|
+
send_command([:sdiff, *keys])
|
124
|
+
end
|
125
|
+
|
126
|
+
# Subtract multiple sets and store the resulting set in a key.
|
127
|
+
#
|
128
|
+
# @param [String] destination destination key
|
129
|
+
# @param [String, Array<String>] keys keys pointing to sets to subtract
|
130
|
+
# @return [Integer] number of elements in the resulting set
|
131
|
+
def sdiffstore(destination, *keys)
|
132
|
+
send_command([:sdiffstore, destination, *keys])
|
133
|
+
end
|
134
|
+
|
135
|
+
# Intersect multiple sets.
|
136
|
+
#
|
137
|
+
# @param [String, Array<String>] keys keys pointing to sets to intersect
|
138
|
+
# @return [Array<String>] members in the intersection
|
139
|
+
def sinter(*keys)
|
140
|
+
send_command([:sinter, *keys])
|
141
|
+
end
|
142
|
+
|
143
|
+
# Intersect multiple sets and store the resulting set in a key.
|
144
|
+
#
|
145
|
+
# @param [String] destination destination key
|
146
|
+
# @param [String, Array<String>] keys keys pointing to sets to intersect
|
147
|
+
# @return [Integer] number of elements in the resulting set
|
148
|
+
def sinterstore(destination, *keys)
|
149
|
+
send_command([:sinterstore, destination, *keys])
|
150
|
+
end
|
151
|
+
|
152
|
+
# Add multiple sets.
|
153
|
+
#
|
154
|
+
# @param [String, Array<String>] keys keys pointing to sets to unify
|
155
|
+
# @return [Array<String>] members in the union
|
156
|
+
def sunion(*keys)
|
157
|
+
send_command([:sunion, *keys])
|
158
|
+
end
|
159
|
+
|
160
|
+
# Add multiple sets and store the resulting set in a key.
|
161
|
+
#
|
162
|
+
# @param [String] destination destination key
|
163
|
+
# @param [String, Array<String>] keys keys pointing to sets to unify
|
164
|
+
# @return [Integer] number of elements in the resulting set
|
165
|
+
def sunionstore(destination, *keys)
|
166
|
+
send_command([:sunionstore, destination, *keys])
|
167
|
+
end
|
168
|
+
|
169
|
+
# Scan a set
|
170
|
+
#
|
171
|
+
# @example Retrieve the first batch of keys in a set
|
172
|
+
# redis.sscan("set", 0)
|
173
|
+
#
|
174
|
+
# @param [String, Integer] cursor the cursor of the iteration
|
175
|
+
# @param [Hash] options
|
176
|
+
# - `:match => String`: only return keys matching the pattern
|
177
|
+
# - `:count => Integer`: return count keys at most per iteration
|
178
|
+
#
|
179
|
+
# @return [String, Array<String>] the next cursor and all found members
|
180
|
+
def sscan(key, cursor, **options)
|
181
|
+
_scan(:sscan, cursor, [key], **options)
|
182
|
+
end
|
183
|
+
|
184
|
+
# Scan a set
|
185
|
+
#
|
186
|
+
# @example Retrieve all of the keys in a set
|
187
|
+
# redis.sscan_each("set").to_a
|
188
|
+
# # => ["key1", "key2", "key3"]
|
189
|
+
#
|
190
|
+
# @param [Hash] options
|
191
|
+
# - `:match => String`: only return keys matching the pattern
|
192
|
+
# - `:count => Integer`: return count keys at most per iteration
|
193
|
+
#
|
194
|
+
# @return [Enumerator] an enumerator for all keys in the set
|
195
|
+
def sscan_each(key, **options, &block)
|
196
|
+
return to_enum(:sscan_each, key, **options) unless block_given?
|
197
|
+
|
198
|
+
cursor = 0
|
199
|
+
loop do
|
200
|
+
cursor, keys = sscan(key, cursor, **options)
|
201
|
+
keys.each(&block)
|
202
|
+
break if cursor == "0"
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|