redis 3.0.0.rc1 → 3.0.0.rc2
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.
- data/.travis.yml +50 -0
- data/.travis/Gemfile +11 -0
- data/CHANGELOG.md +47 -19
- data/README.md +160 -149
- data/Rakefile +15 -50
- data/examples/pubsub.rb +1 -1
- data/examples/unicorn/config.ru +1 -1
- data/examples/unicorn/unicorn.rb +1 -1
- data/lib/redis.rb +790 -390
- data/lib/redis/client.rb +137 -49
- data/lib/redis/connection/hiredis.rb +26 -15
- data/lib/redis/connection/ruby.rb +170 -53
- data/lib/redis/connection/synchrony.rb +23 -35
- data/lib/redis/distributed.rb +92 -32
- data/lib/redis/errors.rb +4 -2
- data/lib/redis/pipeline.rb +17 -6
- data/lib/redis/version.rb +1 -1
- data/redis.gemspec +4 -6
- data/test/blocking_commands_test.rb +42 -0
- data/test/command_map_test.rb +18 -17
- data/test/commands_on_hashes_test.rb +13 -12
- data/test/commands_on_lists_test.rb +35 -45
- data/test/commands_on_sets_test.rb +55 -54
- data/test/commands_on_sorted_sets_test.rb +106 -105
- data/test/commands_on_strings_test.rb +64 -55
- data/test/commands_on_value_types_test.rb +66 -54
- data/test/connection_handling_test.rb +136 -151
- data/test/distributed_blocking_commands_test.rb +33 -40
- data/test/distributed_commands_on_hashes_test.rb +6 -7
- data/test/distributed_commands_on_lists_test.rb +13 -14
- data/test/distributed_commands_on_sets_test.rb +57 -58
- data/test/distributed_commands_on_sorted_sets_test.rb +11 -12
- data/test/distributed_commands_on_strings_test.rb +31 -32
- data/test/distributed_commands_on_value_types_test.rb +61 -46
- data/test/distributed_commands_requiring_clustering_test.rb +108 -108
- data/test/distributed_connection_handling_test.rb +14 -15
- data/test/distributed_internals_test.rb +7 -19
- data/test/distributed_key_tags_test.rb +36 -36
- data/test/distributed_persistence_control_commands_test.rb +17 -14
- data/test/distributed_publish_subscribe_test.rb +61 -69
- data/test/distributed_remote_server_control_commands_test.rb +39 -28
- data/test/distributed_sorting_test.rb +12 -13
- data/test/distributed_test.rb +40 -41
- data/test/distributed_transactions_test.rb +20 -21
- data/test/encoding_test.rb +12 -9
- data/test/error_replies_test.rb +42 -36
- data/test/helper.rb +118 -85
- data/test/helper_test.rb +20 -6
- data/test/internals_test.rb +167 -103
- data/test/lint/blocking_commands.rb +124 -0
- data/test/lint/hashes.rb +115 -93
- data/test/lint/lists.rb +86 -80
- data/test/lint/sets.rb +68 -62
- data/test/lint/sorted_sets.rb +200 -195
- data/test/lint/strings.rb +112 -94
- data/test/lint/value_types.rb +76 -55
- data/test/persistence_control_commands_test.rb +17 -12
- data/test/pipelining_commands_test.rb +135 -126
- data/test/publish_subscribe_test.rb +105 -110
- data/test/remote_server_control_commands_test.rb +74 -58
- data/test/sorting_test.rb +31 -29
- data/test/support/connection/hiredis.rb +1 -0
- data/test/support/connection/ruby.rb +1 -0
- data/test/support/connection/synchrony.rb +17 -0
- data/test/{redis_mock.rb → support/redis_mock.rb} +24 -21
- data/test/support/wire/synchrony.rb +24 -0
- data/test/support/wire/thread.rb +5 -0
- data/test/synchrony_driver.rb +9 -9
- data/test/test.conf +1 -1
- data/test/thread_safety_test.rb +21 -19
- data/test/transactions_test.rb +189 -118
- data/test/unknown_commands_test.rb +9 -8
- data/test/url_param_test.rb +46 -41
- metadata +28 -43
- data/TODO.md +0 -4
- data/benchmarking/thread_safety.rb +0 -38
- data/test/lint/internals.rb +0 -36
data/Rakefile
CHANGED
@@ -24,7 +24,17 @@ task :start do
|
|
24
24
|
false
|
25
25
|
end
|
26
26
|
|
27
|
-
|
27
|
+
unless redis_running
|
28
|
+
unless system("which redis-server")
|
29
|
+
STDERR.puts "redis-server not in PATH"
|
30
|
+
exit 1
|
31
|
+
end
|
32
|
+
|
33
|
+
unless system("redis-server #{REDIS_CNF}")
|
34
|
+
STDERR.puts "could not start redis-server"
|
35
|
+
exit 1
|
36
|
+
end
|
37
|
+
end
|
28
38
|
end
|
29
39
|
|
30
40
|
desc "Stop the Redis server"
|
@@ -35,55 +45,10 @@ task :stop do
|
|
35
45
|
end
|
36
46
|
end
|
37
47
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
desc "Run tests against the Ruby driver"
|
43
|
-
task :ruby do
|
44
|
-
require "cutest"
|
45
|
-
|
46
|
-
Cutest.run(Dir["./test/**/*_test.rb"])
|
47
|
-
end
|
48
|
-
|
49
|
-
desc "Run tests against the hiredis driver"
|
50
|
-
task :hiredis do
|
51
|
-
require "cutest"
|
52
|
-
|
53
|
-
begin
|
54
|
-
require "redis/connection/hiredis"
|
55
|
-
|
56
|
-
puts
|
57
|
-
puts "Running tests against hiredis v#{Hiredis::VERSION}"
|
58
|
-
|
59
|
-
ENV["REDIS_CONNECTION_DRIVER"] = "hiredis"
|
60
|
-
Cutest.run(Dir["./test/**/*_test.rb"])
|
61
|
-
rescue LoadError
|
62
|
-
puts "Skipping tests against hiredis"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
desc "Run tests against the em-synchrony driver"
|
67
|
-
task :synchrony do
|
68
|
-
require "cutest"
|
69
|
-
|
70
|
-
# Synchrony needs 1.9
|
71
|
-
next if RUBY_VERSION < "1.9"
|
72
|
-
|
73
|
-
begin
|
74
|
-
require "redis/connection/synchrony"
|
75
|
-
|
76
|
-
puts
|
77
|
-
puts "Running tests against em-synchrony"
|
78
|
-
|
79
|
-
threaded_tests = ['./test/thread_safety_test.rb']
|
80
|
-
|
81
|
-
ENV["REDIS_CONNECTION_DRIVER"] = "synchrony"
|
82
|
-
Cutest.run(Dir['./test/**/*_test.rb'] - threaded_tests)
|
83
|
-
rescue LoadError
|
84
|
-
puts "Skipping tests against em-synchrony"
|
85
|
-
end
|
86
|
-
end
|
48
|
+
Rake::TestTask.new do |t|
|
49
|
+
t.options = "-v"
|
50
|
+
t.libs << "test"
|
51
|
+
t.test_files = FileList["test/*_test.rb"]
|
87
52
|
end
|
88
53
|
|
89
54
|
task :doc => ["doc:generate", "doc:prepare"]
|
data/examples/pubsub.rb
CHANGED
data/examples/unicorn/config.ru
CHANGED
data/examples/unicorn/unicorn.rb
CHANGED
data/lib/redis.rb
CHANGED
@@ -9,33 +9,19 @@ class Redis
|
|
9
9
|
|
10
10
|
attr :client
|
11
11
|
|
12
|
+
# @deprecated The preferred way to create a new client object is using `#new`.
|
13
|
+
# This method does not actually establish a connection to Redis,
|
14
|
+
# in contrary to what you might expect.
|
12
15
|
def self.connect(options = {})
|
13
|
-
options = options.dup
|
14
|
-
|
15
|
-
url = options.delete(:url) || ENV["REDIS_URL"]
|
16
|
-
if url
|
17
|
-
require "uri"
|
18
|
-
|
19
|
-
uri = URI(url)
|
20
|
-
|
21
|
-
# Require the URL to have at least a host
|
22
|
-
raise ArgumentError, "invalid url" unless uri.host
|
23
|
-
|
24
|
-
options[:host] ||= uri.host
|
25
|
-
options[:port] ||= uri.port
|
26
|
-
options[:password] ||= uri.password
|
27
|
-
options[:db] ||= uri.path[1..-1].to_i
|
28
|
-
end
|
29
|
-
|
30
16
|
new(options)
|
31
17
|
end
|
32
18
|
|
33
19
|
def self.current
|
34
|
-
|
20
|
+
@current ||= Redis.new
|
35
21
|
end
|
36
22
|
|
37
23
|
def self.current=(redis)
|
38
|
-
|
24
|
+
@current = redis
|
39
25
|
end
|
40
26
|
|
41
27
|
include MonitorMixin
|
@@ -43,22 +29,17 @@ class Redis
|
|
43
29
|
def initialize(options = {})
|
44
30
|
@client = Client.new(options)
|
45
31
|
|
46
|
-
|
47
|
-
@synchronizer = lambda { |&block| block.call }
|
48
|
-
else
|
49
|
-
@synchronizer = lambda { |&block| mon_synchronize { block.call } }
|
50
|
-
super() # Monitor#initialize
|
51
|
-
end
|
32
|
+
super() # Monitor#initialize
|
52
33
|
end
|
53
34
|
|
54
35
|
def synchronize
|
55
|
-
|
36
|
+
mon_synchronize { yield(@client) }
|
56
37
|
end
|
57
38
|
|
58
39
|
# Run code without the client reconnecting
|
59
40
|
def without_reconnect(&block)
|
60
|
-
synchronize do
|
61
|
-
|
41
|
+
synchronize do |client|
|
42
|
+
client.without_reconnect(&block)
|
62
43
|
end
|
63
44
|
end
|
64
45
|
|
@@ -68,8 +49,8 @@ class Redis
|
|
68
49
|
# `requirepass` directive in the configuration file
|
69
50
|
# @return [String] `OK`
|
70
51
|
def auth(password)
|
71
|
-
synchronize do
|
72
|
-
|
52
|
+
synchronize do |client|
|
53
|
+
client.call [:auth, password]
|
73
54
|
end
|
74
55
|
end
|
75
56
|
|
@@ -78,9 +59,9 @@ class Redis
|
|
78
59
|
# @param [Fixnum] db zero-based index of the DB to use (0 to 15)
|
79
60
|
# @return [String] `OK`
|
80
61
|
def select(db)
|
81
|
-
synchronize do
|
82
|
-
|
83
|
-
|
62
|
+
synchronize do |client|
|
63
|
+
client.db = db
|
64
|
+
client.call [:select, db]
|
84
65
|
end
|
85
66
|
end
|
86
67
|
|
@@ -89,10 +70,12 @@ class Redis
|
|
89
70
|
# @param [String, Symbol] cmd e.g. "commandstats"
|
90
71
|
# @return [Hash<String, String>]
|
91
72
|
def info(cmd = nil)
|
92
|
-
synchronize do
|
93
|
-
|
73
|
+
synchronize do |client|
|
74
|
+
client.call [:info, cmd].compact do |reply|
|
94
75
|
if reply.kind_of?(String)
|
95
|
-
reply = Hash[
|
76
|
+
reply = Hash[reply.split("\r\n").map do |line|
|
77
|
+
line.split(":", 2) unless line =~ /^(#|$)/
|
78
|
+
end]
|
96
79
|
|
97
80
|
if cmd && cmd.to_s == "commandstats"
|
98
81
|
# Extract nested hashes for INFO COMMANDSTATS
|
@@ -113,8 +96,8 @@ class Redis
|
|
113
96
|
# @return [String, Hash] string reply, or hash when retrieving more than one
|
114
97
|
# property with `CONFIG GET`
|
115
98
|
def config(action, *args)
|
116
|
-
synchronize do
|
117
|
-
|
99
|
+
synchronize do |client|
|
100
|
+
client.call [:config, action, *args] do |reply|
|
118
101
|
if reply.kind_of?(Array) && action == :get
|
119
102
|
Hash[*reply]
|
120
103
|
else
|
@@ -128,8 +111,8 @@ class Redis
|
|
128
111
|
#
|
129
112
|
# @return [String] `OK`
|
130
113
|
def flushdb
|
131
|
-
synchronize do
|
132
|
-
|
114
|
+
synchronize do |client|
|
115
|
+
client.call [:flushdb]
|
133
116
|
end
|
134
117
|
end
|
135
118
|
|
@@ -137,8 +120,8 @@ class Redis
|
|
137
120
|
#
|
138
121
|
# @return [String] `OK`
|
139
122
|
def flushall
|
140
|
-
synchronize do
|
141
|
-
|
123
|
+
synchronize do |client|
|
124
|
+
client.call [:flushall]
|
142
125
|
end
|
143
126
|
end
|
144
127
|
|
@@ -146,8 +129,8 @@ class Redis
|
|
146
129
|
#
|
147
130
|
# @return [String]
|
148
131
|
def save
|
149
|
-
synchronize do
|
150
|
-
|
132
|
+
synchronize do |client|
|
133
|
+
client.call [:save]
|
151
134
|
end
|
152
135
|
end
|
153
136
|
|
@@ -155,8 +138,8 @@ class Redis
|
|
155
138
|
#
|
156
139
|
# @return [String] `OK`
|
157
140
|
def bgsave
|
158
|
-
synchronize do
|
159
|
-
|
141
|
+
synchronize do |client|
|
142
|
+
client.call [:bgsave]
|
160
143
|
end
|
161
144
|
end
|
162
145
|
|
@@ -164,8 +147,8 @@ class Redis
|
|
164
147
|
#
|
165
148
|
# @return [String] `OK`
|
166
149
|
def bgrewriteaof
|
167
|
-
synchronize do
|
168
|
-
|
150
|
+
synchronize do |client|
|
151
|
+
client.call [:bgrewriteaof]
|
169
152
|
end
|
170
153
|
end
|
171
154
|
|
@@ -174,8 +157,8 @@ class Redis
|
|
174
157
|
# @param [String] key
|
175
158
|
# @return [String]
|
176
159
|
def get(key)
|
177
|
-
synchronize do
|
178
|
-
|
160
|
+
synchronize do |client|
|
161
|
+
client.call [:get, key]
|
179
162
|
end
|
180
163
|
end
|
181
164
|
|
@@ -187,8 +170,8 @@ class Redis
|
|
187
170
|
# @param [Fixnum] offset bit offset
|
188
171
|
# @return [Fixnum] `0` or `1`
|
189
172
|
def getbit(key, offset)
|
190
|
-
synchronize do
|
191
|
-
|
173
|
+
synchronize do |client|
|
174
|
+
client.call [:getbit, key, offset]
|
192
175
|
end
|
193
176
|
end
|
194
177
|
|
@@ -200,8 +183,8 @@ class Redis
|
|
200
183
|
# the end of the string
|
201
184
|
# @return [Fixnum] `0` or `1`
|
202
185
|
def getrange(key, start, stop)
|
203
|
-
synchronize do
|
204
|
-
|
186
|
+
synchronize do |client|
|
187
|
+
client.call [:getrange, key, start, stop]
|
205
188
|
end
|
206
189
|
end
|
207
190
|
|
@@ -212,18 +195,24 @@ class Redis
|
|
212
195
|
# @return [String] the old value stored in the key, or `nil` if the key
|
213
196
|
# did not exist
|
214
197
|
def getset(key, value)
|
215
|
-
synchronize do
|
216
|
-
|
198
|
+
synchronize do |client|
|
199
|
+
client.call [:getset, key, value]
|
217
200
|
end
|
218
201
|
end
|
219
202
|
|
220
203
|
# Get the values of all the given keys.
|
221
204
|
#
|
205
|
+
# @example
|
206
|
+
# redis.mget("key1", "key1")
|
207
|
+
# # => ["v1", "v2"]
|
208
|
+
#
|
222
209
|
# @param [Array<String>] keys
|
223
|
-
# @return [Array<String>]
|
210
|
+
# @return [Array<String>] an array of values for the specified keys
|
211
|
+
#
|
212
|
+
# @see #mapped_mget
|
224
213
|
def mget(*keys, &blk)
|
225
|
-
synchronize do
|
226
|
-
|
214
|
+
synchronize do |client|
|
215
|
+
client.call [:mget, *keys], &blk
|
227
216
|
end
|
228
217
|
end
|
229
218
|
|
@@ -233,8 +222,8 @@ class Redis
|
|
233
222
|
# @param [String] value value to append
|
234
223
|
# @return [Fixnum] length of the string after appending
|
235
224
|
def append(key, value)
|
236
|
-
synchronize do
|
237
|
-
|
225
|
+
synchronize do |client|
|
226
|
+
client.call [:append, key, value]
|
238
227
|
end
|
239
228
|
end
|
240
229
|
|
@@ -244,8 +233,8 @@ class Redis
|
|
244
233
|
# @return [Fixnum] the length of the value stored in the key, or 0
|
245
234
|
# if the key does not exist
|
246
235
|
def strlen(key)
|
247
|
-
synchronize do
|
248
|
-
|
236
|
+
synchronize do |client|
|
237
|
+
client.call [:strlen, key]
|
249
238
|
end
|
250
239
|
end
|
251
240
|
|
@@ -254,18 +243,8 @@ class Redis
|
|
254
243
|
# @param [String] key
|
255
244
|
# @return [Hash<String, String>]
|
256
245
|
def hgetall(key)
|
257
|
-
synchronize do
|
258
|
-
|
259
|
-
if reply.kind_of?(Array)
|
260
|
-
hash = Hash.new
|
261
|
-
reply.each_slice(2) do |field, value|
|
262
|
-
hash[field] = value
|
263
|
-
end
|
264
|
-
hash
|
265
|
-
else
|
266
|
-
reply
|
267
|
-
end
|
268
|
-
end
|
246
|
+
synchronize do |client|
|
247
|
+
client.call [:hgetall, key], &_hashify
|
269
248
|
end
|
270
249
|
end
|
271
250
|
|
@@ -275,8 +254,8 @@ class Redis
|
|
275
254
|
# @param [String] field
|
276
255
|
# @return [String]
|
277
256
|
def hget(key, field)
|
278
|
-
synchronize do
|
279
|
-
|
257
|
+
synchronize do |client|
|
258
|
+
client.call [:hget, key, field]
|
280
259
|
end
|
281
260
|
end
|
282
261
|
|
@@ -286,8 +265,8 @@ class Redis
|
|
286
265
|
# @param [String, Array<String>] field
|
287
266
|
# @return [Fixnum] the number of fields that were removed from the hash
|
288
267
|
def hdel(key, field)
|
289
|
-
synchronize do
|
290
|
-
|
268
|
+
synchronize do |client|
|
269
|
+
client.call [:hdel, key, field]
|
291
270
|
end
|
292
271
|
end
|
293
272
|
|
@@ -296,8 +275,8 @@ class Redis
|
|
296
275
|
# @param [String] key
|
297
276
|
# @return [Array<String>]
|
298
277
|
def hkeys(key)
|
299
|
-
synchronize do
|
300
|
-
|
278
|
+
synchronize do |client|
|
279
|
+
client.call [:hkeys, key]
|
301
280
|
end
|
302
281
|
end
|
303
282
|
|
@@ -306,8 +285,8 @@ class Redis
|
|
306
285
|
# @param [String] pattern
|
307
286
|
# @return [Array<String>]
|
308
287
|
def keys(pattern = "*")
|
309
|
-
synchronize do
|
310
|
-
|
288
|
+
synchronize do |client|
|
289
|
+
client.call [:keys, pattern] do |reply|
|
311
290
|
if reply.kind_of?(String)
|
312
291
|
reply.split(" ")
|
313
292
|
else
|
@@ -321,8 +300,8 @@ class Redis
|
|
321
300
|
#
|
322
301
|
# @return [String]
|
323
302
|
def randomkey
|
324
|
-
synchronize do
|
325
|
-
|
303
|
+
synchronize do |client|
|
304
|
+
client.call [:randomkey]
|
326
305
|
end
|
327
306
|
end
|
328
307
|
|
@@ -331,8 +310,23 @@ class Redis
|
|
331
310
|
# @param [String] value
|
332
311
|
# @return [String]
|
333
312
|
def echo(value)
|
334
|
-
synchronize do
|
335
|
-
|
313
|
+
synchronize do |client|
|
314
|
+
client.call [:echo, value]
|
315
|
+
end
|
316
|
+
end
|
317
|
+
|
318
|
+
# Return the server time.
|
319
|
+
#
|
320
|
+
# @example
|
321
|
+
# r.time # => [ 1333093196, 606806 ]
|
322
|
+
#
|
323
|
+
# @return [Array<Fixnum>] tuple of seconds since UNIX epoch and
|
324
|
+
# microseconds in the current second
|
325
|
+
def time
|
326
|
+
synchronize do |client|
|
327
|
+
client.call [:time] do |reply|
|
328
|
+
reply.map(&:to_i) if reply
|
329
|
+
end
|
336
330
|
end
|
337
331
|
end
|
338
332
|
|
@@ -340,8 +334,8 @@ class Redis
|
|
340
334
|
#
|
341
335
|
# @return [String] `PONG`
|
342
336
|
def ping
|
343
|
-
synchronize do
|
344
|
-
|
337
|
+
synchronize do |client|
|
338
|
+
client.call [:ping]
|
345
339
|
end
|
346
340
|
end
|
347
341
|
|
@@ -349,8 +343,8 @@ class Redis
|
|
349
343
|
#
|
350
344
|
# @return [Fixnum]
|
351
345
|
def lastsave
|
352
|
-
synchronize do
|
353
|
-
|
346
|
+
synchronize do |client|
|
347
|
+
client.call [:lastsave]
|
354
348
|
end
|
355
349
|
end
|
356
350
|
|
@@ -358,8 +352,8 @@ class Redis
|
|
358
352
|
#
|
359
353
|
# @return [Fixnum]
|
360
354
|
def dbsize
|
361
|
-
synchronize do
|
362
|
-
|
355
|
+
synchronize do |client|
|
356
|
+
client.call [:dbsize]
|
363
357
|
end
|
364
358
|
end
|
365
359
|
|
@@ -368,8 +362,8 @@ class Redis
|
|
368
362
|
# @param [String] key
|
369
363
|
# @return [Boolean]
|
370
364
|
def exists(key)
|
371
|
-
synchronize do
|
372
|
-
|
365
|
+
synchronize do |client|
|
366
|
+
client.call [:exists, key], &_boolify
|
373
367
|
end
|
374
368
|
end
|
375
369
|
|
@@ -378,8 +372,8 @@ class Redis
|
|
378
372
|
# @param [String] key
|
379
373
|
# @return [Fixnum]
|
380
374
|
def llen(key)
|
381
|
-
synchronize do
|
382
|
-
|
375
|
+
synchronize do |client|
|
376
|
+
client.call [:llen, key]
|
383
377
|
end
|
384
378
|
end
|
385
379
|
|
@@ -390,8 +384,8 @@ class Redis
|
|
390
384
|
# @param [Fixnum] stop stop index
|
391
385
|
# @return [Array<String>]
|
392
386
|
def lrange(key, start, stop)
|
393
|
-
synchronize do
|
394
|
-
|
387
|
+
synchronize do |client|
|
388
|
+
client.call [:lrange, key, start, stop]
|
395
389
|
end
|
396
390
|
end
|
397
391
|
|
@@ -402,8 +396,8 @@ class Redis
|
|
402
396
|
# @param [Fixnum] stop stop index
|
403
397
|
# @return [String] `OK`
|
404
398
|
def ltrim(key, start, stop)
|
405
|
-
synchronize do
|
406
|
-
|
399
|
+
synchronize do |client|
|
400
|
+
client.call [:ltrim, key, start, stop]
|
407
401
|
end
|
408
402
|
end
|
409
403
|
|
@@ -413,8 +407,8 @@ class Redis
|
|
413
407
|
# @param [Fixnum] index
|
414
408
|
# @return [String]
|
415
409
|
def lindex(key, index)
|
416
|
-
synchronize do
|
417
|
-
|
410
|
+
synchronize do |client|
|
411
|
+
client.call [:lindex, key, index]
|
418
412
|
end
|
419
413
|
end
|
420
414
|
|
@@ -427,8 +421,8 @@ class Redis
|
|
427
421
|
# @return [Fixnum] length of the list after the insert operation, or `-1`
|
428
422
|
# when the element `pivot` was not found
|
429
423
|
def linsert(key, where, pivot, value)
|
430
|
-
synchronize do
|
431
|
-
|
424
|
+
synchronize do |client|
|
425
|
+
client.call [:linsert, key, where, pivot, value]
|
432
426
|
end
|
433
427
|
end
|
434
428
|
|
@@ -439,8 +433,8 @@ class Redis
|
|
439
433
|
# @param [String] value
|
440
434
|
# @return [String] `OK`
|
441
435
|
def lset(key, index, value)
|
442
|
-
synchronize do
|
443
|
-
|
436
|
+
synchronize do |client|
|
437
|
+
client.call [:lset, key, index, value]
|
444
438
|
end
|
445
439
|
end
|
446
440
|
|
@@ -454,8 +448,8 @@ class Redis
|
|
454
448
|
# @param [String] value
|
455
449
|
# @return [Fixnum] the number of removed elements
|
456
450
|
def lrem(key, count, value)
|
457
|
-
synchronize do
|
458
|
-
|
451
|
+
synchronize do |client|
|
452
|
+
client.call [:lrem, key, count, value]
|
459
453
|
end
|
460
454
|
end
|
461
455
|
|
@@ -465,8 +459,8 @@ class Redis
|
|
465
459
|
# @param [String] value
|
466
460
|
# @return [Fixnum] the length of the list after the push operation
|
467
461
|
def rpush(key, value)
|
468
|
-
synchronize do
|
469
|
-
|
462
|
+
synchronize do |client|
|
463
|
+
client.call [:rpush, key, value]
|
470
464
|
end
|
471
465
|
end
|
472
466
|
|
@@ -476,8 +470,8 @@ class Redis
|
|
476
470
|
# @param [String] value
|
477
471
|
# @return [Fixnum] the length of the list after the push operation
|
478
472
|
def rpushx(key, value)
|
479
|
-
synchronize do
|
480
|
-
|
473
|
+
synchronize do |client|
|
474
|
+
client.call [:rpushx, key, value]
|
481
475
|
end
|
482
476
|
end
|
483
477
|
|
@@ -487,8 +481,8 @@ class Redis
|
|
487
481
|
# @param [String] value
|
488
482
|
# @return [Fixnum] the length of the list after the push operation
|
489
483
|
def lpush(key, value)
|
490
|
-
synchronize do
|
491
|
-
|
484
|
+
synchronize do |client|
|
485
|
+
client.call [:lpush, key, value]
|
492
486
|
end
|
493
487
|
end
|
494
488
|
|
@@ -498,8 +492,8 @@ class Redis
|
|
498
492
|
# @param [String] value
|
499
493
|
# @return [Fixnum] the length of the list after the push operation
|
500
494
|
def lpushx(key, value)
|
501
|
-
synchronize do
|
502
|
-
|
495
|
+
synchronize do |client|
|
496
|
+
client.call [:lpushx, key, value]
|
503
497
|
end
|
504
498
|
end
|
505
499
|
|
@@ -508,33 +502,73 @@ class Redis
|
|
508
502
|
# @param [String] key
|
509
503
|
# @return [String]
|
510
504
|
def rpop(key)
|
511
|
-
synchronize do
|
512
|
-
|
505
|
+
synchronize do |client|
|
506
|
+
client.call [:rpop, key]
|
507
|
+
end
|
508
|
+
end
|
509
|
+
|
510
|
+
def _bpop(cmd, args)
|
511
|
+
options = {}
|
512
|
+
|
513
|
+
case args.last
|
514
|
+
when Hash
|
515
|
+
options = args.pop
|
516
|
+
when Integer
|
517
|
+
# Issue deprecation notice in obnoxious mode...
|
518
|
+
options[:timeout] = args.pop
|
519
|
+
end
|
520
|
+
|
521
|
+
if args.size > 1
|
522
|
+
# Issue deprecation notice in obnoxious mode...
|
523
|
+
end
|
524
|
+
|
525
|
+
keys = args.flatten
|
526
|
+
timeout = options[:timeout] || 0
|
527
|
+
|
528
|
+
synchronize do |client|
|
529
|
+
client.call_without_timeout [cmd, keys, timeout]
|
513
530
|
end
|
514
531
|
end
|
515
532
|
|
516
533
|
# Remove and get the first element in a list, or block until one is available.
|
517
534
|
#
|
518
|
-
# @
|
519
|
-
#
|
520
|
-
#
|
521
|
-
#
|
535
|
+
# @example With timeout
|
536
|
+
# list, element = redis.blpop("list", :timeout => 5)
|
537
|
+
# # => nil on timeout
|
538
|
+
# # => ["list", "element"] on success
|
539
|
+
# @example Without timeout
|
540
|
+
# list, element = redis.blpop("list")
|
541
|
+
# # => ["list", "element"]
|
542
|
+
# @example Blocking pop on multiple lists
|
543
|
+
# list, element = redis.blpop(["list", "another_list"])
|
544
|
+
# # => ["list", "element"]
|
545
|
+
#
|
546
|
+
# @param [String, Array<String>] keys one or more keys to perform the
|
547
|
+
# blocking pop on
|
548
|
+
# @param [Hash] options
|
549
|
+
# - `:timeout => Fixnum`: timeout in seconds, defaults to no timeout
|
550
|
+
#
|
551
|
+
# @return [nil, [String, String]]
|
552
|
+
# - `nil` when the operation timed out
|
553
|
+
# - tuple of the list that was popped from and element was popped otherwise
|
522
554
|
def blpop(*args)
|
523
|
-
|
524
|
-
@client.call_without_timeout [:blpop, *args]
|
525
|
-
end
|
555
|
+
_bpop(:blpop, args)
|
526
556
|
end
|
527
557
|
|
528
558
|
# Remove and get the last element in a list, or block until one is available.
|
529
559
|
#
|
530
|
-
# @param [Array<String>]
|
531
|
-
#
|
532
|
-
# @
|
533
|
-
#
|
560
|
+
# @param [String, Array<String>] keys one or more keys to perform the
|
561
|
+
# blocking pop on
|
562
|
+
# @param [Hash] options
|
563
|
+
# - `:timeout => Fixnum`: timeout in seconds, defaults to no timeout
|
564
|
+
#
|
565
|
+
# @return [nil, [String, String]]
|
566
|
+
# - `nil` when the operation timed out
|
567
|
+
# - tuple of the list that was popped from and element was popped otherwise
|
568
|
+
#
|
569
|
+
# @see #blpop
|
534
570
|
def brpop(*args)
|
535
|
-
|
536
|
-
@client.call_without_timeout [:brpop, *args]
|
537
|
-
end
|
571
|
+
_bpop(:brpop, args)
|
538
572
|
end
|
539
573
|
|
540
574
|
# Pop a value from a list, push it to another list and return it; or block
|
@@ -542,11 +576,23 @@ class Redis
|
|
542
576
|
#
|
543
577
|
# @param [String] source source key
|
544
578
|
# @param [String] destination destination key
|
545
|
-
# @param [
|
546
|
-
#
|
547
|
-
|
548
|
-
|
549
|
-
|
579
|
+
# @param [Hash] options
|
580
|
+
# - `:timeout => Fixnum`: timeout in seconds, defaults to no timeout
|
581
|
+
#
|
582
|
+
# @return [nil, String]
|
583
|
+
# - `nil` when the operation timed out
|
584
|
+
# - the element was popped and pushed otherwise
|
585
|
+
def brpoplpush(source, destination, options = {})
|
586
|
+
case options
|
587
|
+
when Integer
|
588
|
+
# Issue deprecation notice in obnoxious mode...
|
589
|
+
options = { :timeout => options }
|
590
|
+
end
|
591
|
+
|
592
|
+
timeout = options[:timeout] || 0
|
593
|
+
|
594
|
+
synchronize do |client|
|
595
|
+
client.call_without_timeout [:brpoplpush, source, destination, timeout]
|
550
596
|
end
|
551
597
|
end
|
552
598
|
|
@@ -556,8 +602,8 @@ class Redis
|
|
556
602
|
# @param [String] destination destination key
|
557
603
|
# @return [nil, String] the element, or nil when the source key does not exist
|
558
604
|
def rpoplpush(source, destination)
|
559
|
-
synchronize do
|
560
|
-
|
605
|
+
synchronize do |client|
|
606
|
+
client.call [:rpoplpush, source, destination]
|
561
607
|
end
|
562
608
|
end
|
563
609
|
|
@@ -566,8 +612,8 @@ class Redis
|
|
566
612
|
# @param [String] key
|
567
613
|
# @return [String]
|
568
614
|
def lpop(key)
|
569
|
-
synchronize do
|
570
|
-
|
615
|
+
synchronize do |client|
|
616
|
+
client.call [:lpop, key]
|
571
617
|
end
|
572
618
|
end
|
573
619
|
|
@@ -577,10 +623,10 @@ class Redis
|
|
577
623
|
# @param [Fixnum] length maximum number of entries to return
|
578
624
|
# @return [Array<String>, Fixnum, String] depends on subcommand
|
579
625
|
def slowlog(subcommand, length=nil)
|
580
|
-
synchronize do
|
626
|
+
synchronize do |client|
|
581
627
|
args = [:slowlog, subcommand]
|
582
628
|
args << length if length
|
583
|
-
|
629
|
+
client.call args
|
584
630
|
end
|
585
631
|
end
|
586
632
|
|
@@ -589,8 +635,8 @@ class Redis
|
|
589
635
|
# @param [String] key
|
590
636
|
# @return [Array<String>]
|
591
637
|
def smembers(key)
|
592
|
-
synchronize do
|
593
|
-
|
638
|
+
synchronize do |client|
|
639
|
+
client.call [:smembers, key]
|
594
640
|
end
|
595
641
|
end
|
596
642
|
|
@@ -600,8 +646,8 @@ class Redis
|
|
600
646
|
# @param [String] member
|
601
647
|
# @return [Boolean]
|
602
648
|
def sismember(key, member)
|
603
|
-
synchronize do
|
604
|
-
|
649
|
+
synchronize do |client|
|
650
|
+
client.call [:sismember, key, member], &_boolify
|
605
651
|
end
|
606
652
|
end
|
607
653
|
|
@@ -614,8 +660,8 @@ class Redis
|
|
614
660
|
# array of members is specified, holding the number of members that were
|
615
661
|
# successfully added
|
616
662
|
def sadd(key, member)
|
617
|
-
synchronize do
|
618
|
-
|
663
|
+
synchronize do |client|
|
664
|
+
client.call [:sadd, key, member] do |reply|
|
619
665
|
if member.is_a? Array
|
620
666
|
# Variadic: return integer
|
621
667
|
reply
|
@@ -636,8 +682,8 @@ class Redis
|
|
636
682
|
# array of members is specified, holding the number of members that were
|
637
683
|
# successfully removed
|
638
684
|
def srem(key, member)
|
639
|
-
synchronize do
|
640
|
-
|
685
|
+
synchronize do |client|
|
686
|
+
client.call [:srem, key, member] do |reply|
|
641
687
|
if member.is_a? Array
|
642
688
|
# Variadic: return integer
|
643
689
|
reply
|
@@ -656,8 +702,8 @@ class Redis
|
|
656
702
|
# @param [String] member member to move from `source` to `destination`
|
657
703
|
# @return [Boolean]
|
658
704
|
def smove(source, destination, member)
|
659
|
-
synchronize do
|
660
|
-
|
705
|
+
synchronize do |client|
|
706
|
+
client.call [:smove, source, destination, member], &_boolify
|
661
707
|
end
|
662
708
|
end
|
663
709
|
|
@@ -666,8 +712,8 @@ class Redis
|
|
666
712
|
# @param [String] key
|
667
713
|
# @return [String]
|
668
714
|
def spop(key)
|
669
|
-
synchronize do
|
670
|
-
|
715
|
+
synchronize do |client|
|
716
|
+
client.call [:spop, key]
|
671
717
|
end
|
672
718
|
end
|
673
719
|
|
@@ -676,8 +722,8 @@ class Redis
|
|
676
722
|
# @param [String] key
|
677
723
|
# @return [Fixnum]
|
678
724
|
def scard(key)
|
679
|
-
synchronize do
|
680
|
-
|
725
|
+
synchronize do |client|
|
726
|
+
client.call [:scard, key]
|
681
727
|
end
|
682
728
|
end
|
683
729
|
|
@@ -686,8 +732,8 @@ class Redis
|
|
686
732
|
# @param [String, Array<String>] keys keys pointing to sets to intersect
|
687
733
|
# @return [Array<String>] members in the intersection
|
688
734
|
def sinter(*keys)
|
689
|
-
synchronize do
|
690
|
-
|
735
|
+
synchronize do |client|
|
736
|
+
client.call [:sinter, *keys]
|
691
737
|
end
|
692
738
|
end
|
693
739
|
|
@@ -697,8 +743,8 @@ class Redis
|
|
697
743
|
# @param [String, Array<String>] keys keys pointing to sets to intersect
|
698
744
|
# @return [Fixnum] number of elements in the resulting set
|
699
745
|
def sinterstore(destination, *keys)
|
700
|
-
synchronize do
|
701
|
-
|
746
|
+
synchronize do |client|
|
747
|
+
client.call [:sinterstore, destination, *keys]
|
702
748
|
end
|
703
749
|
end
|
704
750
|
|
@@ -707,8 +753,8 @@ class Redis
|
|
707
753
|
# @param [String, Array<String>] keys keys pointing to sets to unify
|
708
754
|
# @return [Array<String>] members in the union
|
709
755
|
def sunion(*keys)
|
710
|
-
synchronize do
|
711
|
-
|
756
|
+
synchronize do |client|
|
757
|
+
client.call [:sunion, *keys]
|
712
758
|
end
|
713
759
|
end
|
714
760
|
|
@@ -718,8 +764,8 @@ class Redis
|
|
718
764
|
# @param [String, Array<String>] keys keys pointing to sets to unify
|
719
765
|
# @return [Fixnum] number of elements in the resulting set
|
720
766
|
def sunionstore(destination, *keys)
|
721
|
-
synchronize do
|
722
|
-
|
767
|
+
synchronize do |client|
|
768
|
+
client.call [:sunionstore, destination, *keys]
|
723
769
|
end
|
724
770
|
end
|
725
771
|
|
@@ -728,8 +774,8 @@ class Redis
|
|
728
774
|
# @param [String, Array<String>] keys keys pointing to sets to subtract
|
729
775
|
# @return [Array<String>] members in the difference
|
730
776
|
def sdiff(*keys)
|
731
|
-
synchronize do
|
732
|
-
|
777
|
+
synchronize do |client|
|
778
|
+
client.call [:sdiff, *keys]
|
733
779
|
end
|
734
780
|
end
|
735
781
|
|
@@ -739,8 +785,8 @@ class Redis
|
|
739
785
|
# @param [String, Array<String>] keys keys pointing to sets to subtract
|
740
786
|
# @return [Fixnum] number of elements in the resulting set
|
741
787
|
def sdiffstore(destination, *keys)
|
742
|
-
synchronize do
|
743
|
-
|
788
|
+
synchronize do |client|
|
789
|
+
client.call [:sdiffstore, destination, *keys]
|
744
790
|
end
|
745
791
|
end
|
746
792
|
|
@@ -749,23 +795,23 @@ class Redis
|
|
749
795
|
# @param [String] key
|
750
796
|
# @return [String]
|
751
797
|
def srandmember(key)
|
752
|
-
synchronize do
|
753
|
-
|
798
|
+
synchronize do |client|
|
799
|
+
client.call [:srandmember, key]
|
754
800
|
end
|
755
801
|
end
|
756
802
|
|
757
803
|
# Add one or more members to a sorted set, or update the score for members
|
758
804
|
# that already exist.
|
759
805
|
#
|
760
|
-
# @example Add a single `
|
806
|
+
# @example Add a single `[score, member]` pair to a sorted set
|
761
807
|
# redis.zadd("zset", 32.0, "member")
|
762
|
-
# @example Add an array of `
|
808
|
+
# @example Add an array of `[score, member]` pairs to a sorted set
|
763
809
|
# redis.zadd("zset", [[32.0, "a"], [64.0, "b"]])
|
764
810
|
#
|
765
811
|
# @param [String] key
|
766
|
-
# @param [
|
767
|
-
# - a single `
|
768
|
-
# - an array of `
|
812
|
+
# @param [[Float, String], Array<[Float, String]>] args
|
813
|
+
# - a single `[score, member]` pair
|
814
|
+
# - an array of `[score, member]` pairs
|
769
815
|
#
|
770
816
|
# @return [Boolean, Fixnum]
|
771
817
|
# - `Boolean` when a single pair is specified, holding whether or not it was
|
@@ -773,13 +819,13 @@ class Redis
|
|
773
819
|
# - `Fixnum` when an array of pairs is specified, holding the number of
|
774
820
|
# pairs that were **added** to the sorted set
|
775
821
|
def zadd(key, *args)
|
776
|
-
synchronize do
|
822
|
+
synchronize do |client|
|
777
823
|
if args.size == 1 && args[0].is_a?(Array)
|
778
824
|
# Variadic: return integer
|
779
|
-
|
825
|
+
client.call [:zadd, key] + args[0]
|
780
826
|
elsif args.size == 2
|
781
827
|
# Single pair: return boolean
|
782
|
-
|
828
|
+
client.call [:zadd, key, args[0], args[1]], &_boolify
|
783
829
|
else
|
784
830
|
raise ArgumentError, "wrong number of arguments"
|
785
831
|
end
|
@@ -804,8 +850,8 @@ class Redis
|
|
804
850
|
# - `Fixnum` when an array of pairs is specified, holding the number of
|
805
851
|
# members that were removed to the sorted set
|
806
852
|
def zrem(key, member)
|
807
|
-
synchronize do
|
808
|
-
|
853
|
+
synchronize do |client|
|
854
|
+
client.call [:zrem, key, member] do |reply|
|
809
855
|
if member.is_a? Array
|
810
856
|
# Variadic: return integer
|
811
857
|
reply
|
@@ -823,8 +869,8 @@ class Redis
|
|
823
869
|
# @param [String] member
|
824
870
|
# @return [Fixnum]
|
825
871
|
def zrank(key, member)
|
826
|
-
synchronize do
|
827
|
-
|
872
|
+
synchronize do |client|
|
873
|
+
client.call [:zrank, key, member]
|
828
874
|
end
|
829
875
|
end
|
830
876
|
|
@@ -835,8 +881,8 @@ class Redis
|
|
835
881
|
# @param [String] member
|
836
882
|
# @return [Fixnum]
|
837
883
|
def zrevrank(key, member)
|
838
|
-
synchronize do
|
839
|
-
|
884
|
+
synchronize do |client|
|
885
|
+
client.call [:zrevrank, key, member]
|
840
886
|
end
|
841
887
|
end
|
842
888
|
|
@@ -851,8 +897,8 @@ class Redis
|
|
851
897
|
# @param [String] member
|
852
898
|
# @return [Float] score of the member after incrementing it
|
853
899
|
def zincrby(key, increment, member)
|
854
|
-
synchronize do
|
855
|
-
|
900
|
+
synchronize do |client|
|
901
|
+
client.call [:zincrby, key, increment, member] do |reply|
|
856
902
|
Float(reply) if reply
|
857
903
|
end
|
858
904
|
end
|
@@ -867,8 +913,8 @@ class Redis
|
|
867
913
|
# @param [String] key
|
868
914
|
# @return [Fixnum]
|
869
915
|
def zcard(key)
|
870
|
-
synchronize do
|
871
|
-
|
916
|
+
synchronize do |client|
|
917
|
+
client.call [:zcard, key]
|
872
918
|
end
|
873
919
|
end
|
874
920
|
|
@@ -887,17 +933,17 @@ class Redis
|
|
887
933
|
# @param [Hash] options
|
888
934
|
# - `:with_scores => true`: include scores in output
|
889
935
|
#
|
890
|
-
# @return [Array<String>, Array<
|
936
|
+
# @return [Array<String>, Array<[String, Float]>]
|
891
937
|
# - when `:with_scores` is not specified, an array of members
|
892
|
-
# - when `:with_scores` is specified, an array with `
|
938
|
+
# - when `:with_scores` is specified, an array with `[member, score]` pairs
|
893
939
|
def zrange(key, start, stop, options = {})
|
894
940
|
args = []
|
895
941
|
|
896
942
|
with_scores = options[:with_scores] || options[:withscores]
|
897
943
|
args << "WITHSCORES" if with_scores
|
898
944
|
|
899
|
-
synchronize do
|
900
|
-
|
945
|
+
synchronize do |client|
|
946
|
+
client.call [:zrange, key, start, stop, *args] do |reply|
|
901
947
|
if with_scores
|
902
948
|
if reply
|
903
949
|
reply.each_slice(2).map do |member, score|
|
@@ -928,8 +974,8 @@ class Redis
|
|
928
974
|
with_scores = options[:with_scores] || options[:withscores]
|
929
975
|
args << "WITHSCORES" if with_scores
|
930
976
|
|
931
|
-
synchronize do
|
932
|
-
|
977
|
+
synchronize do |client|
|
978
|
+
client.call [:zrevrange, key, start, stop, *args] do |reply|
|
933
979
|
if with_scores
|
934
980
|
if reply
|
935
981
|
reply.each_slice(2).map do |member, score|
|
@@ -967,9 +1013,9 @@ class Redis
|
|
967
1013
|
# - `:limit => [offset, count]`: skip `offset` members, return a maximum of
|
968
1014
|
# `count` members
|
969
1015
|
#
|
970
|
-
# @return [Array<String>, Array<
|
1016
|
+
# @return [Array<String>, Array<[String, Float]>]
|
971
1017
|
# - when `:with_scores` is not specified, an array of members
|
972
|
-
# - when `:with_scores` is specified, an array with `
|
1018
|
+
# - when `:with_scores` is specified, an array with `[member, score]` pairs
|
973
1019
|
def zrangebyscore(key, min, max, options = {})
|
974
1020
|
args = []
|
975
1021
|
|
@@ -979,8 +1025,8 @@ class Redis
|
|
979
1025
|
limit = options[:limit]
|
980
1026
|
args.concat ["LIMIT", *limit] if limit
|
981
1027
|
|
982
|
-
synchronize do
|
983
|
-
|
1028
|
+
synchronize do |client|
|
1029
|
+
client.call [:zrangebyscore, key, min, max, *args] do |reply|
|
984
1030
|
if with_scores
|
985
1031
|
if reply
|
986
1032
|
reply.each_slice(2).map do |member, score|
|
@@ -1017,8 +1063,8 @@ class Redis
|
|
1017
1063
|
limit = options[:limit]
|
1018
1064
|
args.concat ["LIMIT", *limit] if limit
|
1019
1065
|
|
1020
|
-
synchronize do
|
1021
|
-
|
1066
|
+
synchronize do |client|
|
1067
|
+
client.call [:zrevrangebyscore, key, max, min, *args] do |reply|
|
1022
1068
|
if with_scores
|
1023
1069
|
if reply
|
1024
1070
|
reply.each_slice(2).map do |member, score|
|
@@ -1049,9 +1095,9 @@ class Redis
|
|
1049
1095
|
# - inclusive maximum score is specified verbatim
|
1050
1096
|
# - exclusive maximum score is specified by prefixing `(`
|
1051
1097
|
# @return [Fixnum] number of members in within the specified range
|
1052
|
-
def zcount(key,
|
1053
|
-
synchronize do
|
1054
|
-
|
1098
|
+
def zcount(key, min, max)
|
1099
|
+
synchronize do |client|
|
1100
|
+
client.call [:zcount, key, min, max]
|
1055
1101
|
end
|
1056
1102
|
end
|
1057
1103
|
|
@@ -1073,8 +1119,8 @@ class Redis
|
|
1073
1119
|
# - exclusive maximum score is specified by prefixing `(`
|
1074
1120
|
# @return [Fixnum] number of members that were removed
|
1075
1121
|
def zremrangebyscore(key, min, max)
|
1076
|
-
synchronize do
|
1077
|
-
|
1122
|
+
synchronize do |client|
|
1123
|
+
client.call [:zremrangebyscore, key, min, max]
|
1078
1124
|
end
|
1079
1125
|
end
|
1080
1126
|
|
@@ -1092,8 +1138,8 @@ class Redis
|
|
1092
1138
|
# @param [Fixnum] stop stop index
|
1093
1139
|
# @return [Fixnum] number of members that were removed
|
1094
1140
|
def zremrangebyrank(key, start, stop)
|
1095
|
-
synchronize do
|
1096
|
-
|
1141
|
+
synchronize do |client|
|
1142
|
+
client.call [:zremrangebyrank, key, start, stop]
|
1097
1143
|
end
|
1098
1144
|
end
|
1099
1145
|
|
@@ -1107,8 +1153,8 @@ class Redis
|
|
1107
1153
|
# @param [String] member
|
1108
1154
|
# @return [Float] score of the member
|
1109
1155
|
def zscore(key, member)
|
1110
|
-
synchronize do
|
1111
|
-
|
1156
|
+
synchronize do |client|
|
1157
|
+
client.call [:zscore, key, member] do |reply|
|
1112
1158
|
Float(reply) if reply
|
1113
1159
|
end
|
1114
1160
|
end
|
@@ -1129,13 +1175,16 @@ class Redis
|
|
1129
1175
|
# - `:aggregate => String`: aggregate function to use (sum, min, max, ...)
|
1130
1176
|
# @return [Fixnum] number of elements in the resulting sorted set
|
1131
1177
|
def zinterstore(destination, keys, options = {})
|
1132
|
-
|
1133
|
-
|
1134
|
-
|
1135
|
-
|
1178
|
+
args = []
|
1179
|
+
|
1180
|
+
weights = options[:weights]
|
1181
|
+
args.concat ["WEIGHTS", *weights] if weights
|
1182
|
+
|
1183
|
+
aggregate = options[:aggregate]
|
1184
|
+
args.concat ["AGGREGATE", aggregate] if aggregate
|
1136
1185
|
|
1137
|
-
synchronize do
|
1138
|
-
|
1186
|
+
synchronize do |client|
|
1187
|
+
client.call [:zinterstore, destination, keys.size, *(keys + args)]
|
1139
1188
|
end
|
1140
1189
|
end
|
1141
1190
|
|
@@ -1153,13 +1202,16 @@ class Redis
|
|
1153
1202
|
# - `:aggregate => String`: aggregate function to use (sum, min, max, ...)
|
1154
1203
|
# @return [Fixnum] number of elements in the resulting sorted set
|
1155
1204
|
def zunionstore(destination, keys, options = {})
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1205
|
+
args = []
|
1206
|
+
|
1207
|
+
weights = options[:weights]
|
1208
|
+
args.concat ["WEIGHTS", *weights] if weights
|
1209
|
+
|
1210
|
+
aggregate = options[:aggregate]
|
1211
|
+
args.concat ["AGGREGATE", aggregate] if aggregate
|
1160
1212
|
|
1161
|
-
synchronize do
|
1162
|
-
|
1213
|
+
synchronize do |client|
|
1214
|
+
client.call [:zunionstore, destination, keys.size, *(keys + args)]
|
1163
1215
|
end
|
1164
1216
|
end
|
1165
1217
|
|
@@ -1183,8 +1235,8 @@ class Redis
|
|
1183
1235
|
# @param [Fixnum] db
|
1184
1236
|
# @return [Boolean] whether the key was moved or not
|
1185
1237
|
def move(key, db)
|
1186
|
-
synchronize do
|
1187
|
-
|
1238
|
+
synchronize do |client|
|
1239
|
+
client.call [:move, key, db], &_boolify
|
1188
1240
|
end
|
1189
1241
|
end
|
1190
1242
|
|
@@ -1194,18 +1246,18 @@ class Redis
|
|
1194
1246
|
# @param [String] value
|
1195
1247
|
# @return [Boolean] whether the key was set or not
|
1196
1248
|
def setnx(key, value)
|
1197
|
-
synchronize do
|
1198
|
-
|
1249
|
+
synchronize do |client|
|
1250
|
+
client.call [:setnx, key, value], &_boolify
|
1199
1251
|
end
|
1200
1252
|
end
|
1201
1253
|
|
1202
1254
|
# Delete one or more keys.
|
1203
1255
|
#
|
1204
1256
|
# @param [String, Array<String>] keys
|
1205
|
-
# @return [Fixnum] number of keys that were
|
1257
|
+
# @return [Fixnum] number of keys that were deleted
|
1206
1258
|
def del(*keys)
|
1207
|
-
synchronize do
|
1208
|
-
|
1259
|
+
synchronize do |client|
|
1260
|
+
client.call [:del, *keys]
|
1209
1261
|
end
|
1210
1262
|
end
|
1211
1263
|
|
@@ -1215,8 +1267,8 @@ class Redis
|
|
1215
1267
|
# @param [String] new_name
|
1216
1268
|
# @return [String] `OK`
|
1217
1269
|
def rename(old_name, new_name)
|
1218
|
-
synchronize do
|
1219
|
-
|
1270
|
+
synchronize do |client|
|
1271
|
+
client.call [:rename, old_name, new_name]
|
1220
1272
|
end
|
1221
1273
|
end
|
1222
1274
|
|
@@ -1226,20 +1278,30 @@ class Redis
|
|
1226
1278
|
# @param [String] new_name
|
1227
1279
|
# @return [Boolean] whether the key was renamed or not
|
1228
1280
|
def renamenx(old_name, new_name)
|
1229
|
-
synchronize do
|
1230
|
-
|
1281
|
+
synchronize do |client|
|
1282
|
+
client.call [:renamenx, old_name, new_name], &_boolify
|
1231
1283
|
end
|
1232
1284
|
end
|
1233
1285
|
|
1234
1286
|
# Set a key's time to live in seconds.
|
1235
1287
|
#
|
1236
1288
|
# @param [String] key
|
1237
|
-
# @param [Fixnum] seconds time to live
|
1238
|
-
# the key will automatically be deleted
|
1289
|
+
# @param [Fixnum] seconds time to live
|
1239
1290
|
# @return [Boolean] whether the timeout was set or not
|
1240
1291
|
def expire(key, seconds)
|
1241
|
-
synchronize do
|
1242
|
-
|
1292
|
+
synchronize do |client|
|
1293
|
+
client.call [:expire, key, seconds], &_boolify
|
1294
|
+
end
|
1295
|
+
end
|
1296
|
+
|
1297
|
+
# Set a key's time to live in milliseconds.
|
1298
|
+
#
|
1299
|
+
# @param [String] key
|
1300
|
+
# @param [Fixnum] milliseconds time to live
|
1301
|
+
# @return [Boolean] whether the timeout was set or not
|
1302
|
+
def pexpire(key, milliseconds)
|
1303
|
+
synchronize do |client|
|
1304
|
+
client.call [:pexpire, key, milliseconds], &_boolify
|
1243
1305
|
end
|
1244
1306
|
end
|
1245
1307
|
|
@@ -1248,19 +1310,30 @@ class Redis
|
|
1248
1310
|
# @param [String] key
|
1249
1311
|
# @return [Boolean] whether the timeout was removed or not
|
1250
1312
|
def persist(key)
|
1251
|
-
synchronize do
|
1252
|
-
|
1313
|
+
synchronize do |client|
|
1314
|
+
client.call [:persist, key], &_boolify
|
1253
1315
|
end
|
1254
1316
|
end
|
1255
1317
|
|
1256
|
-
# Get the time to live for a key.
|
1318
|
+
# Get the time to live (in seconds) for a key.
|
1257
1319
|
#
|
1258
1320
|
# @param [String] key
|
1259
1321
|
# @return [Fixnum] remaining time to live in seconds, or -1 if the
|
1260
1322
|
# key does not exist or does not have a timeout
|
1261
1323
|
def ttl(key)
|
1262
|
-
synchronize do
|
1263
|
-
|
1324
|
+
synchronize do |client|
|
1325
|
+
client.call [:ttl, key]
|
1326
|
+
end
|
1327
|
+
end
|
1328
|
+
|
1329
|
+
# Get the time to live (in milliseconds) for a key.
|
1330
|
+
#
|
1331
|
+
# @param [String] key
|
1332
|
+
# @return [Fixnum] remaining time to live in milliseconds, or -1 if the
|
1333
|
+
# key does not exist or does not have a timeout
|
1334
|
+
def pttl(key)
|
1335
|
+
synchronize do |client|
|
1336
|
+
client.call [:pttl, key]
|
1264
1337
|
end
|
1265
1338
|
end
|
1266
1339
|
|
@@ -1268,47 +1341,107 @@ class Redis
|
|
1268
1341
|
#
|
1269
1342
|
# @param [String] key
|
1270
1343
|
# @param [Fixnum] unix_time expiry time specified as a UNIX timestamp
|
1271
|
-
# (seconds since January 1, 1970). After this timeout has expired,
|
1272
|
-
# the key will automatically be deleted
|
1273
1344
|
# @return [Boolean] whether the timeout was set or not
|
1274
1345
|
def expireat(key, unix_time)
|
1275
|
-
synchronize do
|
1276
|
-
|
1346
|
+
synchronize do |client|
|
1347
|
+
client.call [:expireat, key, unix_time], &_boolify
|
1277
1348
|
end
|
1278
1349
|
end
|
1279
1350
|
|
1351
|
+
# Set the expiration for a key as number of milliseconds from UNIX Epoch.
|
1352
|
+
#
|
1353
|
+
# @param [String] key
|
1354
|
+
# @param [Fixnum] ms_unix_time expiry time specified as number of milliseconds from UNIX Epoch.
|
1355
|
+
# @return [Boolean] whether the timeout was set or not
|
1356
|
+
def pexpireat(key, ms_unix_time)
|
1357
|
+
synchronize do |client|
|
1358
|
+
client.call [:pexpireat, key, ms_unix_time], &_boolify
|
1359
|
+
end
|
1360
|
+
end
|
1280
1361
|
# Set the string value of a hash field.
|
1362
|
+
#
|
1363
|
+
# @param [String] key
|
1364
|
+
# @param [String] field
|
1365
|
+
# @param [String] value
|
1366
|
+
# @return [Boolean] whether or not the field was **added** to the hash
|
1281
1367
|
def hset(key, field, value)
|
1282
|
-
synchronize do
|
1283
|
-
|
1368
|
+
synchronize do |client|
|
1369
|
+
client.call [:hset, key, field, value], &_boolify
|
1284
1370
|
end
|
1285
1371
|
end
|
1286
1372
|
|
1287
1373
|
# Set the value of a hash field, only if the field does not exist.
|
1374
|
+
#
|
1375
|
+
# @param [String] key
|
1376
|
+
# @param [String] field
|
1377
|
+
# @param [String] value
|
1378
|
+
# @return [Boolean] whether or not the field was **added** to the hash
|
1288
1379
|
def hsetnx(key, field, value)
|
1289
|
-
synchronize do
|
1290
|
-
|
1380
|
+
synchronize do |client|
|
1381
|
+
client.call [:hsetnx, key, field, value], &_boolify
|
1291
1382
|
end
|
1292
1383
|
end
|
1293
1384
|
|
1294
|
-
# Set
|
1385
|
+
# Set one or more hash values.
|
1386
|
+
#
|
1387
|
+
# @example
|
1388
|
+
# redis.hmset("hash", "f1", "v1", "f2", "v2")
|
1389
|
+
# # => "OK"
|
1390
|
+
#
|
1391
|
+
# @param [String] key
|
1392
|
+
# @param [Array<String>] attrs array of fields and values
|
1393
|
+
# @return `"OK"`
|
1394
|
+
#
|
1395
|
+
# @see #mapped_hmset
|
1295
1396
|
def hmset(key, *attrs)
|
1296
|
-
synchronize do
|
1297
|
-
|
1397
|
+
synchronize do |client|
|
1398
|
+
client.call [:hmset, key, *attrs]
|
1298
1399
|
end
|
1299
1400
|
end
|
1300
1401
|
|
1402
|
+
# Set one or more hash values.
|
1403
|
+
#
|
1404
|
+
# @example
|
1405
|
+
# redis.hmset("hash", { "f1" => "v1", "f2" => "v2" })
|
1406
|
+
# # => "OK"
|
1407
|
+
#
|
1408
|
+
# @param [String] key
|
1409
|
+
# @param [Hash] hash fields mapping to values
|
1410
|
+
# @return `"OK"`
|
1411
|
+
#
|
1412
|
+
# @see #hmset
|
1301
1413
|
def mapped_hmset(key, hash)
|
1302
1414
|
hmset(key, *hash.to_a.flatten)
|
1303
1415
|
end
|
1304
1416
|
|
1305
1417
|
# Get the values of all the given hash fields.
|
1418
|
+
#
|
1419
|
+
# @example
|
1420
|
+
# redis.hmget("hash", "f1", "f2")
|
1421
|
+
# # => ["v1", "v2"]
|
1422
|
+
#
|
1423
|
+
# @param [String] key
|
1424
|
+
# @param [Array<String>] fields array of fields
|
1425
|
+
# @return [Array<String>] an array of values for the specified fields
|
1426
|
+
#
|
1427
|
+
# @see #mapped_hmget
|
1306
1428
|
def hmget(key, *fields, &blk)
|
1307
|
-
synchronize do
|
1308
|
-
|
1429
|
+
synchronize do |client|
|
1430
|
+
client.call [:hmget, key, *fields], &blk
|
1309
1431
|
end
|
1310
1432
|
end
|
1311
1433
|
|
1434
|
+
# Get the values of all the given hash fields.
|
1435
|
+
#
|
1436
|
+
# @example
|
1437
|
+
# redis.hmget("hash", "f1", "f2")
|
1438
|
+
# # => { "f1" => "v1", "f2" => "v2" }
|
1439
|
+
#
|
1440
|
+
# @param [String] key
|
1441
|
+
# @param [Array<String>] fields array of fields
|
1442
|
+
# @return [Hash] a hash mapping the specified fields to their values
|
1443
|
+
#
|
1444
|
+
# @see #hmget
|
1312
1445
|
def mapped_hmget(key, *fields)
|
1313
1446
|
hmget(key, *fields) do |reply|
|
1314
1447
|
if reply.kind_of?(Array)
|
@@ -1324,118 +1457,224 @@ class Redis
|
|
1324
1457
|
end
|
1325
1458
|
|
1326
1459
|
# Get the number of fields in a hash.
|
1460
|
+
#
|
1461
|
+
# @param [String] key
|
1462
|
+
# @return [Fixnum] number of fields in the hash
|
1327
1463
|
def hlen(key)
|
1328
|
-
synchronize do
|
1329
|
-
|
1464
|
+
synchronize do |client|
|
1465
|
+
client.call [:hlen, key]
|
1330
1466
|
end
|
1331
1467
|
end
|
1332
1468
|
|
1333
1469
|
# Get all the values in a hash.
|
1470
|
+
#
|
1471
|
+
# @param [String] key
|
1472
|
+
# @return [Array<String>]
|
1334
1473
|
def hvals(key)
|
1335
|
-
synchronize do
|
1336
|
-
|
1474
|
+
synchronize do |client|
|
1475
|
+
client.call [:hvals, key]
|
1337
1476
|
end
|
1338
1477
|
end
|
1339
1478
|
|
1340
|
-
# Increment the integer value of a hash field by the given number.
|
1479
|
+
# Increment the integer value of a hash field by the given integer number.
|
1480
|
+
#
|
1481
|
+
# @param [String] key
|
1482
|
+
# @param [String] field
|
1483
|
+
# @param [Fixnum] increment
|
1484
|
+
# @return [Fixnum] value of the field after incrementing it
|
1341
1485
|
def hincrby(key, field, increment)
|
1342
|
-
synchronize do
|
1343
|
-
|
1486
|
+
synchronize do |client|
|
1487
|
+
client.call [:hincrby, key, field, increment]
|
1344
1488
|
end
|
1345
1489
|
end
|
1346
1490
|
|
1347
|
-
#
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1491
|
+
# Increment the numeric value of a hash field by the given float number.
|
1492
|
+
#
|
1493
|
+
# @param [String] key
|
1494
|
+
# @param [String] field
|
1495
|
+
# @param [Float] increment
|
1496
|
+
# @return [Float] value of the field after incrementing it
|
1497
|
+
def hincrbyfloat(key, field, increment)
|
1498
|
+
synchronize do |client|
|
1499
|
+
client.call [:hincrbyfloat, key, field, increment] do |reply|
|
1500
|
+
Float(reply) if reply
|
1501
|
+
end
|
1351
1502
|
end
|
1352
1503
|
end
|
1353
1504
|
|
1354
1505
|
# Determine if a hash field exists.
|
1506
|
+
#
|
1507
|
+
# @param [String] key
|
1508
|
+
# @param [String] field
|
1509
|
+
# @return [Boolean] whether or not the field exists in the hash
|
1355
1510
|
def hexists(key, field)
|
1356
|
-
synchronize do
|
1357
|
-
|
1511
|
+
synchronize do |client|
|
1512
|
+
client.call [:hexists, key, field], &_boolify
|
1358
1513
|
end
|
1359
1514
|
end
|
1360
1515
|
|
1361
1516
|
# Listen for all requests received by the server in real time.
|
1517
|
+
#
|
1518
|
+
# There is no way to interrupt this command.
|
1519
|
+
#
|
1520
|
+
# @yield a block to be called for every line of output
|
1521
|
+
# @yieldparam [String] line timestamp and command that was executed
|
1362
1522
|
def monitor(&block)
|
1363
|
-
synchronize do
|
1364
|
-
|
1523
|
+
synchronize do |client|
|
1524
|
+
client.call_loop([:monitor], &block)
|
1365
1525
|
end
|
1366
1526
|
end
|
1367
1527
|
|
1368
1528
|
def debug(*args)
|
1369
|
-
synchronize do
|
1370
|
-
|
1529
|
+
synchronize do |client|
|
1530
|
+
client.call [:debug, *args]
|
1371
1531
|
end
|
1372
1532
|
end
|
1373
1533
|
|
1374
1534
|
def object(*args)
|
1375
|
-
synchronize do
|
1376
|
-
|
1535
|
+
synchronize do |client|
|
1536
|
+
client.call [:object, *args]
|
1377
1537
|
end
|
1378
1538
|
end
|
1379
1539
|
|
1380
1540
|
# Internal command used for replication.
|
1381
1541
|
def sync
|
1382
|
-
synchronize do
|
1383
|
-
|
1542
|
+
synchronize do |client|
|
1543
|
+
client.call [:sync]
|
1384
1544
|
end
|
1385
1545
|
end
|
1386
1546
|
|
1387
1547
|
# Set the string value of a key.
|
1548
|
+
#
|
1549
|
+
# @param [String] key
|
1550
|
+
# @param [String] value
|
1551
|
+
# @return `"OK"`
|
1388
1552
|
def set(key, value)
|
1389
|
-
synchronize do
|
1390
|
-
|
1553
|
+
synchronize do |client|
|
1554
|
+
client.call [:set, key, value]
|
1391
1555
|
end
|
1392
1556
|
end
|
1393
1557
|
|
1394
1558
|
alias :[]= :set
|
1395
1559
|
|
1396
1560
|
# Sets or clears the bit at offset in the string value stored at key.
|
1561
|
+
#
|
1562
|
+
# @param [String] key
|
1563
|
+
# @param [Fixnum] offset bit offset
|
1564
|
+
# @param [Fixnum] value bit value `0` or `1`
|
1565
|
+
# @return [Fixnum] the original bit value stored at `offset`
|
1397
1566
|
def setbit(key, offset, value)
|
1398
|
-
synchronize do
|
1399
|
-
|
1567
|
+
synchronize do |client|
|
1568
|
+
client.call [:setbit, key, offset, value]
|
1400
1569
|
end
|
1401
1570
|
end
|
1402
1571
|
|
1403
|
-
# Set the
|
1572
|
+
# Set the time to live in seconds of a key.
|
1573
|
+
#
|
1574
|
+
# @param [String] key
|
1575
|
+
# @param [Fixnum] ttl
|
1576
|
+
# @param [String] value
|
1577
|
+
# @return `"OK"`
|
1404
1578
|
def setex(key, ttl, value)
|
1405
|
-
synchronize do
|
1406
|
-
|
1579
|
+
synchronize do |client|
|
1580
|
+
client.call [:setex, key, ttl, value]
|
1581
|
+
end
|
1582
|
+
end
|
1583
|
+
|
1584
|
+
# Set the time to live in milliseconds of a key.
|
1585
|
+
#
|
1586
|
+
# @param [String] key
|
1587
|
+
# @param [Fixnum] ttl
|
1588
|
+
# @param [String] value
|
1589
|
+
# @return `"OK"`
|
1590
|
+
def psetex(key, ttl, value)
|
1591
|
+
synchronize do |client|
|
1592
|
+
client.call [:psetex, key, ttl, value]
|
1407
1593
|
end
|
1408
1594
|
end
|
1409
1595
|
|
1410
1596
|
# Overwrite part of a string at key starting at the specified offset.
|
1597
|
+
#
|
1598
|
+
# @param [String] key
|
1599
|
+
# @param [Fixnum] offset byte offset
|
1600
|
+
# @param [String] value
|
1601
|
+
# @return [Fixnum] length of the string after it was modified
|
1411
1602
|
def setrange(key, offset, value)
|
1412
|
-
synchronize do
|
1413
|
-
|
1603
|
+
synchronize do |client|
|
1604
|
+
client.call [:setrange, key, offset, value]
|
1414
1605
|
end
|
1415
1606
|
end
|
1416
1607
|
|
1417
|
-
# Set
|
1608
|
+
# Set one or more values.
|
1609
|
+
#
|
1610
|
+
# @example
|
1611
|
+
# redis.mset("key1", "v1", "key2", "v2")
|
1612
|
+
# # => "OK"
|
1613
|
+
#
|
1614
|
+
# @param [Array<String>] args array of keys and values
|
1615
|
+
# @return `"OK"`
|
1616
|
+
#
|
1617
|
+
# @see #mapped_mset
|
1418
1618
|
def mset(*args)
|
1419
|
-
synchronize do
|
1420
|
-
|
1619
|
+
synchronize do |client|
|
1620
|
+
client.call [:mset, *args]
|
1421
1621
|
end
|
1422
1622
|
end
|
1423
1623
|
|
1624
|
+
# Set one or more values.
|
1625
|
+
#
|
1626
|
+
# @example
|
1627
|
+
# redis.mapped_mset({ "f1" => "v1", "f2" => "v2" })
|
1628
|
+
# # => "OK"
|
1629
|
+
#
|
1630
|
+
# @param [Hash] hash keys mapping to values
|
1631
|
+
# @return `"OK"`
|
1632
|
+
#
|
1633
|
+
# @see #mset
|
1424
1634
|
def mapped_mset(hash)
|
1425
1635
|
mset(*hash.to_a.flatten)
|
1426
1636
|
end
|
1427
1637
|
|
1428
|
-
# Set
|
1638
|
+
# Set one or more values, only if none of the keys exist.
|
1639
|
+
#
|
1640
|
+
# @example
|
1641
|
+
# redis.msetnx("key1", "v1", "key2", "v2")
|
1642
|
+
# # => true
|
1643
|
+
#
|
1644
|
+
# @param [Array<String>] args array of keys and values
|
1645
|
+
# @return [Boolean] whether or not all values were set
|
1646
|
+
#
|
1647
|
+
# @see #mapped_msetnx
|
1429
1648
|
def msetnx(*args)
|
1430
|
-
synchronize do
|
1431
|
-
|
1649
|
+
synchronize do |client|
|
1650
|
+
client.call [:msetnx, *args], &_boolify
|
1432
1651
|
end
|
1433
1652
|
end
|
1434
1653
|
|
1654
|
+
# Set one or more values, only if none of the keys exist.
|
1655
|
+
#
|
1656
|
+
# @example
|
1657
|
+
# redis.msetnx({ "key1" => "v1", "key2" => "v2" })
|
1658
|
+
# # => true
|
1659
|
+
#
|
1660
|
+
# @param [Hash] hash keys mapping to values
|
1661
|
+
# @return [Boolean] whether or not all values were set
|
1662
|
+
#
|
1663
|
+
# @see #msetnx
|
1435
1664
|
def mapped_msetnx(hash)
|
1436
1665
|
msetnx(*hash.to_a.flatten)
|
1437
1666
|
end
|
1438
1667
|
|
1668
|
+
# Get the values of all the given keys.
|
1669
|
+
#
|
1670
|
+
# @example
|
1671
|
+
# redis.mapped_mget("key1", "key1")
|
1672
|
+
# # => { "key1" => "v1", "key2" => "v2" }
|
1673
|
+
#
|
1674
|
+
# @param [Array<String>] keys array of keys
|
1675
|
+
# @return [Hash] a hash mapping the specified keys to their values
|
1676
|
+
#
|
1677
|
+
# @see #mget
|
1439
1678
|
def mapped_mget(*keys)
|
1440
1679
|
mget(*keys) do |reply|
|
1441
1680
|
if reply.kind_of?(Array)
|
@@ -1451,45 +1690,133 @@ class Redis
|
|
1451
1690
|
end
|
1452
1691
|
|
1453
1692
|
# Sort the elements in a list, set or sorted set.
|
1693
|
+
#
|
1694
|
+
# @example Retrieve the first 2 elements from an alphabetically sorted "list"
|
1695
|
+
# redis.sort("list", :order => "alpha", :limit => [0, 2])
|
1696
|
+
# # => ["a", "b"]
|
1697
|
+
# @example Store an alphabetically descending list in "target"
|
1698
|
+
# redis.sort("list", :order => "desc alpha", :store => "target")
|
1699
|
+
# # => 26
|
1700
|
+
#
|
1701
|
+
# @param [String] key
|
1702
|
+
# @param [Hash] options
|
1703
|
+
# - `:by => String`: use external key to sort elements by
|
1704
|
+
# - `:limit => [offset, count]`: skip `offset` elements, return a maximum
|
1705
|
+
# of `count` elements
|
1706
|
+
# - `:get => [String, Array<String>]`: single key or array of keys to
|
1707
|
+
# retrieve per element in the result
|
1708
|
+
# - `:order => String`: combination of `ASC`, `DESC` and optionally `ALPHA`
|
1709
|
+
# - `:store => String`: key to store the result at
|
1710
|
+
#
|
1711
|
+
# @return [Array<String>, Array<Array<String>>, Fixnum]
|
1712
|
+
# - when `:get` is not specified, or holds a single element, an array of elements
|
1713
|
+
# - when `:get` is specified, and holds more than one element, an array of
|
1714
|
+
# elements where every element is an array with the result for every
|
1715
|
+
# element specified in `:get`
|
1716
|
+
# - when `:store` is specified, the number of elements in the stored result
|
1454
1717
|
def sort(key, options = {})
|
1455
|
-
|
1456
|
-
|
1457
|
-
|
1458
|
-
|
1459
|
-
|
1460
|
-
|
1461
|
-
|
1718
|
+
args = []
|
1719
|
+
|
1720
|
+
by = options[:by]
|
1721
|
+
args.concat ["BY", by] if by
|
1722
|
+
|
1723
|
+
limit = options[:limit]
|
1724
|
+
args.concat ["LIMIT", *limit] if limit
|
1462
1725
|
|
1463
|
-
|
1464
|
-
|
1726
|
+
get = Array(options[:get])
|
1727
|
+
args.concat ["GET"].product(get).flatten unless get.empty?
|
1728
|
+
|
1729
|
+
order = options[:order]
|
1730
|
+
args.concat order.split(" ") if order
|
1731
|
+
|
1732
|
+
store = options[:store]
|
1733
|
+
args.concat ["STORE", store] if store
|
1734
|
+
|
1735
|
+
synchronize do |client|
|
1736
|
+
client.call [:sort, key, *args] do |reply|
|
1737
|
+
if get.size > 1
|
1738
|
+
if reply
|
1739
|
+
reply.each_slice(get.size).to_a
|
1740
|
+
end
|
1741
|
+
else
|
1742
|
+
reply
|
1743
|
+
end
|
1744
|
+
end
|
1465
1745
|
end
|
1466
1746
|
end
|
1467
1747
|
|
1468
1748
|
# Increment the integer value of a key by one.
|
1749
|
+
#
|
1750
|
+
# @example
|
1751
|
+
# redis.incr("value")
|
1752
|
+
# # => 6
|
1753
|
+
#
|
1754
|
+
# @param [String] key
|
1755
|
+
# @return [Fixnum] value after incrementing it
|
1469
1756
|
def incr(key)
|
1470
|
-
synchronize do
|
1471
|
-
|
1757
|
+
synchronize do |client|
|
1758
|
+
client.call [:incr, key]
|
1472
1759
|
end
|
1473
1760
|
end
|
1474
1761
|
|
1475
|
-
# Increment the integer value of a key by the given number.
|
1762
|
+
# Increment the integer value of a key by the given integer number.
|
1763
|
+
#
|
1764
|
+
# @example
|
1765
|
+
# redis.incrby("value", 5)
|
1766
|
+
# # => 10
|
1767
|
+
#
|
1768
|
+
# @param [String] key
|
1769
|
+
# @param [Fixnum] increment
|
1770
|
+
# @return [Fixnum] value after incrementing it
|
1476
1771
|
def incrby(key, increment)
|
1477
|
-
synchronize do
|
1478
|
-
|
1772
|
+
synchronize do |client|
|
1773
|
+
client.call [:incrby, key, increment]
|
1774
|
+
end
|
1775
|
+
end
|
1776
|
+
|
1777
|
+
# Increment the numeric value of a key by the given float number.
|
1778
|
+
#
|
1779
|
+
# @example
|
1780
|
+
# redis.incrbyfloat("value", 1.23)
|
1781
|
+
# # => 1.23
|
1782
|
+
#
|
1783
|
+
# @param [String] key
|
1784
|
+
# @param [Float] increment
|
1785
|
+
# @return [Float] value after incrementing it
|
1786
|
+
def incrbyfloat(key, increment)
|
1787
|
+
synchronize do |client|
|
1788
|
+
client.call [:incrbyfloat, key, increment] do |reply|
|
1789
|
+
Float(reply) if reply
|
1790
|
+
end
|
1479
1791
|
end
|
1480
1792
|
end
|
1481
1793
|
|
1482
1794
|
# Decrement the integer value of a key by one.
|
1795
|
+
#
|
1796
|
+
# @example
|
1797
|
+
# redis.decr("value")
|
1798
|
+
# # => 4
|
1799
|
+
#
|
1800
|
+
# @param [String] key
|
1801
|
+
# @return [Fixnum] value after decrementing it
|
1483
1802
|
def decr(key)
|
1484
|
-
synchronize do
|
1485
|
-
|
1803
|
+
synchronize do |client|
|
1804
|
+
client.call [:decr, key]
|
1486
1805
|
end
|
1487
1806
|
end
|
1488
1807
|
|
1489
1808
|
# Decrement the integer value of a key by the given number.
|
1809
|
+
#
|
1810
|
+
# @example
|
1811
|
+
# redis.decrby("value", 5)
|
1812
|
+
# # => 0
|
1813
|
+
#
|
1814
|
+
# @param [String] key
|
1815
|
+
# @param [Fixnum] decrement
|
1816
|
+
# @return [Fixnum] value after decrementing it
|
1490
1817
|
def decrby(key, decrement)
|
1491
|
-
synchronize do
|
1492
|
-
|
1818
|
+
synchronize do |client|
|
1819
|
+
client.call [:decrby, key, decrement]
|
1493
1820
|
end
|
1494
1821
|
end
|
1495
1822
|
|
@@ -1498,29 +1825,31 @@ class Redis
|
|
1498
1825
|
# @param [String] key
|
1499
1826
|
# @return [String] `string`, `list`, `set`, `zset`, `hash` or `none`
|
1500
1827
|
def type(key)
|
1501
|
-
synchronize do
|
1502
|
-
|
1828
|
+
synchronize do |client|
|
1829
|
+
client.call [:type, key]
|
1503
1830
|
end
|
1504
1831
|
end
|
1505
1832
|
|
1506
1833
|
# Close the connection.
|
1834
|
+
#
|
1835
|
+
# @return [String] `OK`
|
1507
1836
|
def quit
|
1508
|
-
synchronize do
|
1837
|
+
synchronize do |client|
|
1509
1838
|
begin
|
1510
|
-
|
1839
|
+
client.call [:quit]
|
1511
1840
|
rescue ConnectionError
|
1512
1841
|
ensure
|
1513
|
-
|
1842
|
+
client.disconnect
|
1514
1843
|
end
|
1515
1844
|
end
|
1516
1845
|
end
|
1517
1846
|
|
1518
1847
|
# Synchronously save the dataset to disk and then shut down the server.
|
1519
1848
|
def shutdown
|
1520
|
-
synchronize do
|
1521
|
-
|
1849
|
+
synchronize do |client|
|
1850
|
+
client.without_reconnect do
|
1522
1851
|
begin
|
1523
|
-
|
1852
|
+
client.call [:shutdown]
|
1524
1853
|
rescue ConnectionError
|
1525
1854
|
# This means Redis has probably exited.
|
1526
1855
|
nil
|
@@ -1531,16 +1860,16 @@ class Redis
|
|
1531
1860
|
|
1532
1861
|
# Make the server a slave of another instance, or promote it as master.
|
1533
1862
|
def slaveof(host, port)
|
1534
|
-
synchronize do
|
1535
|
-
|
1863
|
+
synchronize do |client|
|
1864
|
+
client.call [:slaveof, host, port]
|
1536
1865
|
end
|
1537
1866
|
end
|
1538
1867
|
|
1539
1868
|
def pipelined
|
1540
|
-
synchronize do
|
1869
|
+
synchronize do |client|
|
1541
1870
|
begin
|
1542
1871
|
original, @client = @client, Pipeline.new
|
1543
|
-
yield
|
1872
|
+
yield(self)
|
1544
1873
|
original.call_pipeline(@client)
|
1545
1874
|
ensure
|
1546
1875
|
@client = original
|
@@ -1549,31 +1878,98 @@ class Redis
|
|
1549
1878
|
end
|
1550
1879
|
|
1551
1880
|
# Watch the given keys to determine execution of the MULTI/EXEC block.
|
1881
|
+
#
|
1882
|
+
# Using a block is optional, but is necessary for thread-safety.
|
1883
|
+
#
|
1884
|
+
# An `#unwatch` is automatically issued if an exception is raised within the
|
1885
|
+
# block that is a subclass of StandardError and is not a ConnectionError.
|
1886
|
+
#
|
1887
|
+
# @example With a block
|
1888
|
+
# redis.watch("key") do
|
1889
|
+
# if redis.get("key") == "some value"
|
1890
|
+
# redis.multi do |multi|
|
1891
|
+
# multi.set("key", "other value")
|
1892
|
+
# multi.incr("counter")
|
1893
|
+
# end
|
1894
|
+
# else
|
1895
|
+
# redis.unwatch
|
1896
|
+
# end
|
1897
|
+
# end
|
1898
|
+
# # => ["OK", 6]
|
1899
|
+
#
|
1900
|
+
# @example Without a block
|
1901
|
+
# redis.watch("key")
|
1902
|
+
# # => "OK"
|
1903
|
+
#
|
1904
|
+
# @param [String, Array<String>] keys one or more keys to watch
|
1905
|
+
# @return [Object] if using a block, returns the return value of the block
|
1906
|
+
# @return [String] if not using a block, returns `OK`
|
1907
|
+
#
|
1908
|
+
# @see #unwatch
|
1909
|
+
# @see #multi
|
1552
1910
|
def watch(*keys)
|
1553
|
-
synchronize do
|
1554
|
-
|
1911
|
+
synchronize do |client|
|
1912
|
+
client.call [:watch, *keys]
|
1913
|
+
|
1914
|
+
if block_given?
|
1915
|
+
begin
|
1916
|
+
yield
|
1917
|
+
rescue ConnectionError
|
1918
|
+
raise
|
1919
|
+
rescue StandardError
|
1920
|
+
unwatch
|
1921
|
+
raise
|
1922
|
+
end
|
1923
|
+
end
|
1555
1924
|
end
|
1556
1925
|
end
|
1557
1926
|
|
1558
1927
|
# Forget about all watched keys.
|
1928
|
+
#
|
1929
|
+
# @return [String] `OK`
|
1930
|
+
#
|
1931
|
+
# @see #watch
|
1932
|
+
# @see #multi
|
1559
1933
|
def unwatch
|
1560
|
-
synchronize do
|
1561
|
-
|
1562
|
-
end
|
1563
|
-
end
|
1564
|
-
|
1565
|
-
# Execute all commands issued after MULTI.
|
1566
|
-
def exec
|
1567
|
-
synchronize do
|
1568
|
-
@client.call [:exec]
|
1934
|
+
synchronize do |client|
|
1935
|
+
client.call [:unwatch]
|
1569
1936
|
end
|
1570
1937
|
end
|
1571
1938
|
|
1572
1939
|
# Mark the start of a transaction block.
|
1940
|
+
#
|
1941
|
+
# Passing a block is optional.
|
1942
|
+
#
|
1943
|
+
# @example With a block
|
1944
|
+
# redis.multi do |multi|
|
1945
|
+
# multi.set("key", "value")
|
1946
|
+
# multi.incr("counter")
|
1947
|
+
# end # => ["OK", 6]
|
1948
|
+
#
|
1949
|
+
# @example Without a block
|
1950
|
+
# redis.multi
|
1951
|
+
# # => "OK"
|
1952
|
+
# redis.set("key", "value")
|
1953
|
+
# # => "QUEUED"
|
1954
|
+
# redis.incr("counter")
|
1955
|
+
# # => "QUEUED"
|
1956
|
+
# redis.exec
|
1957
|
+
# # => ["OK", 6]
|
1958
|
+
#
|
1959
|
+
# @yield [multi] the commands that are called inside this block are cached
|
1960
|
+
# and written to the server upon returning from it
|
1961
|
+
# @yieldparam [Redis] multi `self`
|
1962
|
+
#
|
1963
|
+
# @return [String, Array<...>]
|
1964
|
+
# - when a block is not given, `OK`
|
1965
|
+
# - when a block is given, an array with replies
|
1966
|
+
#
|
1967
|
+
# @see #watch
|
1968
|
+
# @see #unwatch
|
1573
1969
|
def multi
|
1574
|
-
synchronize do
|
1970
|
+
synchronize do |client|
|
1575
1971
|
if !block_given?
|
1576
|
-
|
1972
|
+
client.call [:multi]
|
1577
1973
|
else
|
1578
1974
|
begin
|
1579
1975
|
pipeline = Pipeline::Multi.new
|
@@ -1587,100 +1983,94 @@ class Redis
|
|
1587
1983
|
end
|
1588
1984
|
end
|
1589
1985
|
|
1986
|
+
# Execute all commands issued after MULTI.
|
1987
|
+
#
|
1988
|
+
# Only call this method when `#multi` was called **without** a block.
|
1989
|
+
#
|
1990
|
+
# @return [nil, Array<...>]
|
1991
|
+
# - when commands were not executed, `nil`
|
1992
|
+
# - when commands were executed, an array with their replies
|
1993
|
+
#
|
1994
|
+
# @see #multi
|
1995
|
+
# @see #discard
|
1996
|
+
def exec
|
1997
|
+
synchronize do |client|
|
1998
|
+
client.call [:exec]
|
1999
|
+
end
|
2000
|
+
end
|
2001
|
+
|
2002
|
+
# Discard all commands issued after MULTI.
|
2003
|
+
#
|
2004
|
+
# Only call this method when `#multi` was called **without** a block.
|
2005
|
+
#
|
2006
|
+
# @return `"OK"`
|
2007
|
+
#
|
2008
|
+
# @see #multi
|
2009
|
+
# @see #exec
|
2010
|
+
def discard
|
2011
|
+
synchronize do |client|
|
2012
|
+
client.call [:discard]
|
2013
|
+
end
|
2014
|
+
end
|
2015
|
+
|
1590
2016
|
# Post a message to a channel.
|
1591
2017
|
def publish(channel, message)
|
1592
|
-
synchronize do
|
1593
|
-
|
2018
|
+
synchronize do |client|
|
2019
|
+
client.call [:publish, channel, message]
|
1594
2020
|
end
|
1595
2021
|
end
|
1596
2022
|
|
1597
2023
|
def subscribed?
|
1598
|
-
synchronize do
|
1599
|
-
|
2024
|
+
synchronize do |client|
|
2025
|
+
client.kind_of? SubscribedClient
|
1600
2026
|
end
|
1601
2027
|
end
|
1602
2028
|
|
1603
2029
|
# Stop listening for messages posted to the given channels.
|
1604
2030
|
def unsubscribe(*channels)
|
1605
|
-
synchronize do
|
2031
|
+
synchronize do |client|
|
1606
2032
|
raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed?
|
1607
|
-
|
2033
|
+
client.unsubscribe(*channels)
|
1608
2034
|
end
|
1609
2035
|
end
|
1610
2036
|
|
1611
2037
|
# Stop listening for messages posted to channels matching the given patterns.
|
1612
2038
|
def punsubscribe(*channels)
|
1613
|
-
synchronize do
|
2039
|
+
synchronize do |client|
|
1614
2040
|
raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed?
|
1615
|
-
|
2041
|
+
client.punsubscribe(*channels)
|
1616
2042
|
end
|
1617
2043
|
end
|
1618
2044
|
|
1619
2045
|
# Listen for messages published to the given channels.
|
1620
2046
|
def subscribe(*channels, &block)
|
1621
|
-
synchronize do
|
1622
|
-
|
2047
|
+
synchronize do |client|
|
2048
|
+
_subscription(:subscribe, channels, block)
|
1623
2049
|
end
|
1624
2050
|
end
|
1625
2051
|
|
1626
2052
|
# Listen for messages published to channels matching the given patterns.
|
1627
2053
|
def psubscribe(*channels, &block)
|
1628
|
-
synchronize do
|
1629
|
-
|
2054
|
+
synchronize do |client|
|
2055
|
+
_subscription(:psubscribe, channels, block)
|
1630
2056
|
end
|
1631
2057
|
end
|
1632
2058
|
|
1633
2059
|
def id
|
1634
|
-
synchronize do
|
1635
|
-
|
2060
|
+
synchronize do |client|
|
2061
|
+
client.id
|
1636
2062
|
end
|
1637
2063
|
end
|
1638
2064
|
|
1639
2065
|
def inspect
|
1640
|
-
synchronize do
|
1641
|
-
"#<Redis client v#{Redis::VERSION}
|
2066
|
+
synchronize do |client|
|
2067
|
+
"#<Redis client v#{Redis::VERSION} for #{client.id}>"
|
1642
2068
|
end
|
1643
2069
|
end
|
1644
2070
|
|
1645
2071
|
def method_missing(command, *args)
|
1646
|
-
synchronize do
|
1647
|
-
|
1648
|
-
end
|
1649
|
-
end
|
1650
|
-
|
1651
|
-
class CommandOptions
|
1652
|
-
def initialize(options)
|
1653
|
-
@result = []
|
1654
|
-
@options = options
|
1655
|
-
yield(self)
|
1656
|
-
end
|
1657
|
-
|
1658
|
-
def bool(name)
|
1659
|
-
insert(name) { |argument, value| [argument] }
|
1660
|
-
end
|
1661
|
-
|
1662
|
-
def value(name)
|
1663
|
-
insert(name) { |argument, value| [argument, value] }
|
1664
|
-
end
|
1665
|
-
|
1666
|
-
def splat(name)
|
1667
|
-
insert(name) { |argument, value| [argument, *value] }
|
1668
|
-
end
|
1669
|
-
|
1670
|
-
def multi(name)
|
1671
|
-
insert(name) { |argument, value| [argument].product(Array(value)).flatten }
|
1672
|
-
end
|
1673
|
-
|
1674
|
-
def words(name)
|
1675
|
-
insert(name) { |argument, value| value.split(" ") }
|
1676
|
-
end
|
1677
|
-
|
1678
|
-
def to_a
|
1679
|
-
@result
|
1680
|
-
end
|
1681
|
-
|
1682
|
-
def insert(name)
|
1683
|
-
@result += yield(name.to_s.upcase.gsub("_", ""), @options[name]) if @options[name]
|
2072
|
+
synchronize do |client|
|
2073
|
+
client.call [command, *args]
|
1684
2074
|
end
|
1685
2075
|
end
|
1686
2076
|
|
@@ -1695,7 +2085,17 @@ private
|
|
1695
2085
|
}
|
1696
2086
|
end
|
1697
2087
|
|
1698
|
-
def
|
2088
|
+
def _hashify
|
2089
|
+
lambda { |array|
|
2090
|
+
hash = Hash.new
|
2091
|
+
array.each_slice(2) do |field, value|
|
2092
|
+
hash[field] = value
|
2093
|
+
end
|
2094
|
+
hash
|
2095
|
+
}
|
2096
|
+
end
|
2097
|
+
|
2098
|
+
def _subscription(method, channels, block)
|
1699
2099
|
return @client.call [method, *channels] if subscribed?
|
1700
2100
|
|
1701
2101
|
begin
|