redis 2.0.0 → 2.2.1
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/.gitignore +8 -0
- data/CHANGELOG.md +49 -0
- data/README.md +208 -0
- data/Rakefile +183 -73
- data/TODO.md +4 -0
- data/benchmarking/logging.rb +62 -0
- data/benchmarking/pipeline.rb +51 -0
- data/benchmarking/speed.rb +21 -0
- data/benchmarking/suite.rb +24 -0
- data/benchmarking/thread_safety.rb +38 -0
- data/benchmarking/worker.rb +71 -0
- data/examples/basic.rb +15 -0
- data/examples/dist_redis.rb +43 -0
- data/examples/incr-decr.rb +17 -0
- data/examples/list.rb +26 -0
- data/examples/pubsub.rb +31 -0
- data/examples/sets.rb +36 -0
- data/examples/unicorn/config.ru +3 -0
- data/examples/unicorn/unicorn.rb +20 -0
- data/lib/redis/client.rb +149 -165
- data/lib/redis/connection/command_helper.rb +45 -0
- data/lib/redis/connection/hiredis.rb +49 -0
- data/lib/redis/connection/registry.rb +12 -0
- data/lib/redis/connection/ruby.rb +135 -0
- data/lib/redis/connection/synchrony.rb +129 -0
- data/lib/redis/connection.rb +9 -0
- data/lib/redis/distributed.rb +182 -7
- data/lib/redis/pipeline.rb +22 -1
- data/lib/redis/subscribe.rb +19 -4
- data/lib/redis/version.rb +3 -0
- data/lib/redis.rb +715 -155
- data/redis.gemspec +24 -0
- data/test/commands_on_hashes_test.rb +32 -0
- data/test/commands_on_lists_test.rb +60 -0
- data/test/commands_on_sets_test.rb +78 -0
- data/test/commands_on_sorted_sets_test.rb +109 -0
- data/test/commands_on_strings_test.rb +80 -0
- data/test/commands_on_value_types_test.rb +88 -0
- data/test/connection_handling_test.rb +88 -0
- data/test/db/.gitignore +1 -0
- data/test/distributed_blocking_commands_test.rb +53 -0
- data/test/distributed_commands_on_hashes_test.rb +12 -0
- data/test/distributed_commands_on_lists_test.rb +24 -0
- data/test/distributed_commands_on_sets_test.rb +85 -0
- data/test/distributed_commands_on_strings_test.rb +50 -0
- data/test/distributed_commands_on_value_types_test.rb +73 -0
- data/test/distributed_commands_requiring_clustering_test.rb +148 -0
- data/test/distributed_connection_handling_test.rb +25 -0
- data/test/distributed_internals_test.rb +27 -0
- data/test/distributed_key_tags_test.rb +53 -0
- data/test/distributed_persistence_control_commands_test.rb +24 -0
- data/test/distributed_publish_subscribe_test.rb +101 -0
- data/test/distributed_remote_server_control_commands_test.rb +43 -0
- data/test/distributed_sorting_test.rb +21 -0
- data/test/distributed_test.rb +59 -0
- data/test/distributed_transactions_test.rb +34 -0
- data/test/encoding_test.rb +16 -0
- data/test/error_replies_test.rb +53 -0
- data/test/helper.rb +145 -0
- data/test/internals_test.rb +160 -0
- data/test/lint/hashes.rb +114 -0
- data/test/lint/internals.rb +37 -0
- data/test/lint/lists.rb +93 -0
- data/test/lint/sets.rb +66 -0
- data/test/lint/sorted_sets.rb +167 -0
- data/test/lint/strings.rb +137 -0
- data/test/lint/value_types.rb +84 -0
- data/test/persistence_control_commands_test.rb +22 -0
- data/test/pipelining_commands_test.rb +123 -0
- data/test/publish_subscribe_test.rb +158 -0
- data/test/redis_mock.rb +80 -0
- data/test/remote_server_control_commands_test.rb +82 -0
- data/test/sorting_test.rb +44 -0
- data/test/synchrony_driver.rb +57 -0
- data/test/test.conf +8 -0
- data/test/thread_safety_test.rb +30 -0
- data/test/transactions_test.rb +100 -0
- data/test/unknown_commands_test.rb +14 -0
- data/test/url_param_test.rb +60 -0
- metadata +130 -22
- data/README.markdown +0 -120
data/lib/redis/distributed.rb
CHANGED
|
@@ -23,7 +23,7 @@ class Redis
|
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def node_for(key)
|
|
26
|
-
@ring.get_node(key_tag(key) || key)
|
|
26
|
+
@ring.get_node(key_tag(key.to_s) || key.to_s)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def nodes
|
|
@@ -34,90 +34,139 @@ class Redis
|
|
|
34
34
|
@ring.add_node Redis.connect(@default_options.merge(:url => url))
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
# Close the connection.
|
|
37
38
|
def quit
|
|
38
39
|
on_each_node :quit
|
|
39
40
|
end
|
|
40
41
|
|
|
42
|
+
# Change the selected database for the current connection.
|
|
41
43
|
def select(db)
|
|
42
44
|
on_each_node :select, db
|
|
43
45
|
end
|
|
44
46
|
|
|
47
|
+
# Ping the server.
|
|
45
48
|
def ping
|
|
46
49
|
on_each_node :ping
|
|
47
50
|
end
|
|
48
51
|
|
|
52
|
+
# Remove all keys from all databases.
|
|
49
53
|
def flushall
|
|
50
54
|
on_each_node :flushall
|
|
51
55
|
end
|
|
52
56
|
|
|
57
|
+
# Determine if a key exists.
|
|
53
58
|
def exists(key)
|
|
54
59
|
node_for(key).exists(key)
|
|
55
60
|
end
|
|
56
61
|
|
|
57
|
-
|
|
58
|
-
|
|
62
|
+
# Delete a key.
|
|
63
|
+
def del(*args)
|
|
64
|
+
keys_per_node = args.group_by { |key| node_for(key) }
|
|
65
|
+
keys_per_node.inject(0) do |sum, (node, keys)|
|
|
66
|
+
sum + node.del(*keys)
|
|
67
|
+
end
|
|
59
68
|
end
|
|
60
69
|
|
|
70
|
+
# Determine the type stored at key.
|
|
61
71
|
def type(key)
|
|
62
72
|
node_for(key).type(key)
|
|
63
73
|
end
|
|
64
74
|
|
|
75
|
+
# Find all keys matching the given pattern.
|
|
65
76
|
def keys(glob = "*")
|
|
66
77
|
on_each_node(:keys, glob).flatten
|
|
67
78
|
end
|
|
68
79
|
|
|
80
|
+
# Return a random key from the keyspace.
|
|
69
81
|
def randomkey
|
|
70
82
|
raise CannotDistribute, :randomkey
|
|
71
83
|
end
|
|
72
84
|
|
|
85
|
+
# Rename a key.
|
|
73
86
|
def rename(old_name, new_name)
|
|
74
87
|
ensure_same_node(:rename, old_name, new_name) do |node|
|
|
75
88
|
node.rename(old_name, new_name)
|
|
76
89
|
end
|
|
77
90
|
end
|
|
78
91
|
|
|
92
|
+
# Rename a key, only if the new key does not exist.
|
|
79
93
|
def renamenx(old_name, new_name)
|
|
80
94
|
ensure_same_node(:renamenx, old_name, new_name) do |node|
|
|
81
95
|
node.renamenx(old_name, new_name)
|
|
82
96
|
end
|
|
83
97
|
end
|
|
84
98
|
|
|
99
|
+
# Return the number of keys in the selected database.
|
|
85
100
|
def dbsize
|
|
86
101
|
on_each_node :dbsize
|
|
87
102
|
end
|
|
88
103
|
|
|
104
|
+
# Set a key's time to live in seconds.
|
|
89
105
|
def expire(key, seconds)
|
|
90
106
|
node_for(key).expire(key, seconds)
|
|
91
107
|
end
|
|
92
108
|
|
|
109
|
+
# Set the expiration for a key as a UNIX timestamp.
|
|
93
110
|
def expireat(key, unix_time)
|
|
94
111
|
node_for(key).expireat(key, unix_time)
|
|
95
112
|
end
|
|
96
113
|
|
|
114
|
+
# Remove the expiration from a key.
|
|
115
|
+
def persist(key)
|
|
116
|
+
node_for(key).persist(key)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
# Get the time to live for a key.
|
|
97
120
|
def ttl(key)
|
|
98
121
|
node_for(key).ttl(key)
|
|
99
122
|
end
|
|
100
123
|
|
|
124
|
+
# Move a key to another database.
|
|
101
125
|
def move(key, db)
|
|
102
126
|
node_for(key).move(key, db)
|
|
103
127
|
end
|
|
104
128
|
|
|
129
|
+
# Remove all keys from the current database.
|
|
105
130
|
def flushdb
|
|
106
131
|
on_each_node :flushdb
|
|
107
132
|
end
|
|
108
133
|
|
|
134
|
+
# Set the string value of a key.
|
|
109
135
|
def set(key, value)
|
|
110
136
|
node_for(key).set(key, value)
|
|
111
137
|
end
|
|
112
138
|
|
|
139
|
+
# Sets or clears the bit at offset in the string value stored at key.
|
|
140
|
+
def setbit(key, offset, value)
|
|
141
|
+
node_for(key).setbit(key, offset, value)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# Overwrite part of a string at key starting at the specified offset.
|
|
145
|
+
def setrange(key, offset, value)
|
|
146
|
+
node_for(key).setrange(key, offset, value)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# Set the value and expiration of a key.
|
|
113
150
|
def setex(key, ttl, value)
|
|
114
151
|
node_for(key).setex(key, ttl, value)
|
|
115
152
|
end
|
|
116
153
|
|
|
154
|
+
# Get the value of a key.
|
|
117
155
|
def get(key)
|
|
118
156
|
node_for(key).get(key)
|
|
119
157
|
end
|
|
120
158
|
|
|
159
|
+
# Returns the bit value at offset in the string value stored at key.
|
|
160
|
+
def getbit(key, offset)
|
|
161
|
+
node_for(key).getbit(key, offset)
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Get a substring of the string stored at a key.
|
|
165
|
+
def getrange(key, start, stop)
|
|
166
|
+
node_for(key).getrange(key, start, stop)
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# Set the string value of a key and return its old value.
|
|
121
170
|
def getset(key, value)
|
|
122
171
|
node_for(key).getset(key, value)
|
|
123
172
|
end
|
|
@@ -126,6 +175,7 @@ class Redis
|
|
|
126
175
|
get(key)
|
|
127
176
|
end
|
|
128
177
|
|
|
178
|
+
# Append a value to a key.
|
|
129
179
|
def append(key, value)
|
|
130
180
|
node_for(key).append(key, value)
|
|
131
181
|
end
|
|
@@ -138,6 +188,7 @@ class Redis
|
|
|
138
188
|
set(key, value)
|
|
139
189
|
end
|
|
140
190
|
|
|
191
|
+
# Get the values of all the given keys.
|
|
141
192
|
def mget(*keys)
|
|
142
193
|
raise CannotDistribute, :mget
|
|
143
194
|
end
|
|
@@ -146,10 +197,12 @@ class Redis
|
|
|
146
197
|
raise CannotDistribute, :mapped_mget
|
|
147
198
|
end
|
|
148
199
|
|
|
200
|
+
# Set the value of a key, only if the key does not exist.
|
|
149
201
|
def setnx(key, value)
|
|
150
202
|
node_for(key).setnx(key, value)
|
|
151
203
|
end
|
|
152
204
|
|
|
205
|
+
# Set multiple keys to multiple values.
|
|
153
206
|
def mset(*args)
|
|
154
207
|
raise CannotDistribute, :mset
|
|
155
208
|
end
|
|
@@ -158,6 +211,7 @@ class Redis
|
|
|
158
211
|
mset(*hash.to_a.flatten)
|
|
159
212
|
end
|
|
160
213
|
|
|
214
|
+
# Set multiple keys to multiple values, only if none of the keys exist.
|
|
161
215
|
def msetnx(*args)
|
|
162
216
|
raise CannotDistribute, :msetnx
|
|
163
217
|
end
|
|
@@ -166,246 +220,335 @@ class Redis
|
|
|
166
220
|
raise CannotDistribute, :mapped_msetnx
|
|
167
221
|
end
|
|
168
222
|
|
|
223
|
+
# Increment the integer value of a key by one.
|
|
169
224
|
def incr(key)
|
|
170
225
|
node_for(key).incr(key)
|
|
171
226
|
end
|
|
172
227
|
|
|
228
|
+
# Increment the integer value of a key by the given number.
|
|
173
229
|
def incrby(key, increment)
|
|
174
230
|
node_for(key).incrby(key, increment)
|
|
175
231
|
end
|
|
176
232
|
|
|
233
|
+
# Decrement the integer value of a key by one.
|
|
177
234
|
def decr(key)
|
|
178
235
|
node_for(key).decr(key)
|
|
179
236
|
end
|
|
180
237
|
|
|
238
|
+
# Decrement the integer value of a key by the given number.
|
|
181
239
|
def decrby(key, decrement)
|
|
182
240
|
node_for(key).decrby(key, decrement)
|
|
183
241
|
end
|
|
184
242
|
|
|
243
|
+
# Append a value to a list.
|
|
185
244
|
def rpush(key, value)
|
|
186
245
|
node_for(key).rpush(key, value)
|
|
187
246
|
end
|
|
188
247
|
|
|
248
|
+
# Prepend a value to a list.
|
|
189
249
|
def lpush(key, value)
|
|
190
250
|
node_for(key).lpush(key, value)
|
|
191
251
|
end
|
|
192
252
|
|
|
253
|
+
# Get the length of a list.
|
|
193
254
|
def llen(key)
|
|
194
255
|
node_for(key).llen(key)
|
|
195
256
|
end
|
|
196
257
|
|
|
258
|
+
# Get a range of elements from a list.
|
|
197
259
|
def lrange(key, start, stop)
|
|
198
260
|
node_for(key).lrange(key, start, stop)
|
|
199
261
|
end
|
|
200
262
|
|
|
263
|
+
# Trim a list to the specified range.
|
|
201
264
|
def ltrim(key, start, stop)
|
|
202
265
|
node_for(key).ltrim(key, start, stop)
|
|
203
266
|
end
|
|
204
267
|
|
|
268
|
+
# Get an element from a list by its index.
|
|
205
269
|
def lindex(key, index)
|
|
206
270
|
node_for(key).lindex(key, index)
|
|
207
271
|
end
|
|
208
272
|
|
|
273
|
+
# Set the value of an element in a list by its index.
|
|
209
274
|
def lset(key, index, value)
|
|
210
275
|
node_for(key).lset(key, index, value)
|
|
211
276
|
end
|
|
212
277
|
|
|
278
|
+
# Remove elements from a list.
|
|
213
279
|
def lrem(key, count, value)
|
|
214
280
|
node_for(key).lrem(key, count, value)
|
|
215
281
|
end
|
|
216
282
|
|
|
283
|
+
# Remove and get the first element in a list.
|
|
217
284
|
def lpop(key)
|
|
218
285
|
node_for(key).lpop(key)
|
|
219
286
|
end
|
|
220
287
|
|
|
288
|
+
# Remove and get the last element in a list.
|
|
221
289
|
def rpop(key)
|
|
222
290
|
node_for(key).rpop(key)
|
|
223
291
|
end
|
|
224
292
|
|
|
293
|
+
# Remove the last element in a list, append it to another list and return
|
|
294
|
+
# it.
|
|
225
295
|
def rpoplpush(source, destination)
|
|
226
296
|
ensure_same_node(:rpoplpush, source, destination) do |node|
|
|
227
297
|
node.rpoplpush(source, destination)
|
|
228
298
|
end
|
|
229
299
|
end
|
|
230
300
|
|
|
301
|
+
# Remove and get the first element in a list, or block until one is
|
|
302
|
+
# available.
|
|
231
303
|
def blpop(key, timeout)
|
|
232
304
|
node_for(key).blpop(key, timeout)
|
|
233
305
|
end
|
|
234
306
|
|
|
307
|
+
# Remove and get the last element in a list, or block until one is
|
|
308
|
+
# available.
|
|
235
309
|
def brpop(key, timeout)
|
|
236
310
|
node_for(key).brpop(key, timeout)
|
|
237
311
|
end
|
|
238
312
|
|
|
313
|
+
# Pop a value from a list, push it to another list and return it; or block
|
|
314
|
+
# until one is available.
|
|
315
|
+
def brpoplpush(source, destination, timeout)
|
|
316
|
+
ensure_same_node(:brpoplpush, source, destination) do |node|
|
|
317
|
+
node.brpoplpush(source, destination, timeout)
|
|
318
|
+
end
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
# Add a member to a set.
|
|
239
322
|
def sadd(key, value)
|
|
240
323
|
node_for(key).sadd(key, value)
|
|
241
324
|
end
|
|
242
325
|
|
|
326
|
+
# Remove a member from a set.
|
|
243
327
|
def srem(key, value)
|
|
244
328
|
node_for(key).srem(key, value)
|
|
245
329
|
end
|
|
246
330
|
|
|
331
|
+
# Remove and return a random member from a set.
|
|
247
332
|
def spop(key)
|
|
248
333
|
node_for(key).spop(key)
|
|
249
334
|
end
|
|
250
335
|
|
|
336
|
+
# Move a member from one set to another.
|
|
251
337
|
def smove(source, destination, member)
|
|
252
338
|
ensure_same_node(:smove, source, destination) do |node|
|
|
253
339
|
node.smove(source, destination, member)
|
|
254
340
|
end
|
|
255
341
|
end
|
|
256
342
|
|
|
343
|
+
# Get the number of members in a set.
|
|
257
344
|
def scard(key)
|
|
258
345
|
node_for(key).scard(key)
|
|
259
346
|
end
|
|
260
347
|
|
|
348
|
+
# Determine if a given value is a member of a set.
|
|
261
349
|
def sismember(key, member)
|
|
262
350
|
node_for(key).sismember(key, member)
|
|
263
351
|
end
|
|
264
352
|
|
|
353
|
+
# Intersect multiple sets.
|
|
265
354
|
def sinter(*keys)
|
|
266
355
|
ensure_same_node(:sinter, *keys) do |node|
|
|
267
356
|
node.sinter(*keys)
|
|
268
357
|
end
|
|
269
358
|
end
|
|
270
359
|
|
|
360
|
+
# Intersect multiple sets and store the resulting set in a key.
|
|
271
361
|
def sinterstore(destination, *keys)
|
|
272
362
|
ensure_same_node(:sinterstore, destination, *keys) do |node|
|
|
273
363
|
node.sinterstore(destination, *keys)
|
|
274
364
|
end
|
|
275
365
|
end
|
|
276
366
|
|
|
367
|
+
# Add multiple sets.
|
|
277
368
|
def sunion(*keys)
|
|
278
369
|
ensure_same_node(:sunion, *keys) do |node|
|
|
279
370
|
node.sunion(*keys)
|
|
280
371
|
end
|
|
281
372
|
end
|
|
282
373
|
|
|
374
|
+
# Add multiple sets and store the resulting set in a key.
|
|
283
375
|
def sunionstore(destination, *keys)
|
|
284
376
|
ensure_same_node(:sunionstore, destination, *keys) do |node|
|
|
285
377
|
node.sunionstore(destination, *keys)
|
|
286
378
|
end
|
|
287
379
|
end
|
|
288
380
|
|
|
381
|
+
# Subtract multiple sets.
|
|
289
382
|
def sdiff(*keys)
|
|
290
383
|
ensure_same_node(:sdiff, *keys) do |node|
|
|
291
384
|
node.sdiff(*keys)
|
|
292
385
|
end
|
|
293
386
|
end
|
|
294
387
|
|
|
388
|
+
# Subtract multiple sets and store the resulting set in a key.
|
|
295
389
|
def sdiffstore(destination, *keys)
|
|
296
390
|
ensure_same_node(:sdiffstore, destination, *keys) do |node|
|
|
297
391
|
node.sdiffstore(destination, *keys)
|
|
298
392
|
end
|
|
299
393
|
end
|
|
300
394
|
|
|
395
|
+
# Get all the members in a set.
|
|
301
396
|
def smembers(key)
|
|
302
397
|
node_for(key).smembers(key)
|
|
303
398
|
end
|
|
304
399
|
|
|
400
|
+
# Get a random member from a set.
|
|
305
401
|
def srandmember(key)
|
|
306
402
|
node_for(key).srandmember(key)
|
|
307
403
|
end
|
|
308
404
|
|
|
405
|
+
# Add a member to a sorted set, or update its score if it already exists.
|
|
309
406
|
def zadd(key, score, member)
|
|
310
407
|
node_for(key).zadd(key, score, member)
|
|
311
408
|
end
|
|
312
409
|
|
|
410
|
+
# Remove a member from a sorted set.
|
|
313
411
|
def zrem(key, member)
|
|
314
412
|
node_for(key).zrem(key, member)
|
|
315
413
|
end
|
|
316
414
|
|
|
415
|
+
# Increment the score of a member in a sorted set.
|
|
317
416
|
def zincrby(key, increment, member)
|
|
318
417
|
node_for(key).zincrby(key, increment, member)
|
|
319
418
|
end
|
|
320
419
|
|
|
420
|
+
# Return a range of members in a sorted set, by index.
|
|
321
421
|
def zrange(key, start, stop, options = {})
|
|
322
422
|
node_for(key).zrange(key, start, stop, options)
|
|
323
423
|
end
|
|
324
424
|
|
|
425
|
+
# Determine the index of a member in a sorted set.
|
|
325
426
|
def zrank(key, member)
|
|
326
427
|
node_for(key).zrank(key, member)
|
|
327
428
|
end
|
|
328
429
|
|
|
430
|
+
# Determine the index of a member in a sorted set, with scores ordered from
|
|
431
|
+
# high to low.
|
|
329
432
|
def zrevrank(key, member)
|
|
330
433
|
node_for(key).zrevrank(key, member)
|
|
331
434
|
end
|
|
332
435
|
|
|
436
|
+
# Return a range of members in a sorted set, by index, with scores ordered
|
|
437
|
+
# from high to low.
|
|
333
438
|
def zrevrange(key, start, stop, options = {})
|
|
334
439
|
node_for(key).zrevrange(key, start, stop, options)
|
|
335
440
|
end
|
|
336
441
|
|
|
442
|
+
# Remove all members in a sorted set within the given scores.
|
|
337
443
|
def zremrangebyscore(key, min, max)
|
|
338
444
|
node_for(key).zremrangebyscore(key, min, max)
|
|
339
445
|
end
|
|
340
446
|
|
|
447
|
+
# Remove all members in a sorted set within the given indexes.
|
|
341
448
|
def zremrangebyrank(key, start, stop)
|
|
342
449
|
node_for(key).zremrangebyrank(key, start, stop)
|
|
343
450
|
end
|
|
344
451
|
|
|
452
|
+
# Return a range of members in a sorted set, by score.
|
|
345
453
|
def zrangebyscore(key, min, max, options = {})
|
|
346
454
|
node_for(key).zrangebyscore(key, min, max, options)
|
|
347
455
|
end
|
|
348
456
|
|
|
457
|
+
# Return a range of members in a sorted set, by score, with scores ordered
|
|
458
|
+
# from high to low.
|
|
459
|
+
def zrevrangebyscore(key, max, min, options = {})
|
|
460
|
+
node_for(key).zrevrangebyscore(key, max, min, options)
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
# Get the number of members in a sorted set.
|
|
349
464
|
def zcard(key)
|
|
350
465
|
node_for(key).zcard(key)
|
|
351
466
|
end
|
|
352
467
|
|
|
468
|
+
# Get the score associated with the given member in a sorted set.
|
|
353
469
|
def zscore(key, member)
|
|
354
470
|
node_for(key).zscore(key, member)
|
|
355
471
|
end
|
|
356
472
|
|
|
473
|
+
# Intersect multiple sorted sets and store the resulting sorted set in a new
|
|
474
|
+
# key.
|
|
357
475
|
def zinterstore(destination, keys, options = {})
|
|
358
476
|
ensure_same_node(:zinterstore, destination, *keys) do |node|
|
|
359
477
|
node.zinterstore(destination, keys, options)
|
|
360
478
|
end
|
|
361
479
|
end
|
|
362
480
|
|
|
481
|
+
# Add multiple sorted sets and store the resulting sorted set in a new key.
|
|
363
482
|
def zunionstore(destination, keys, options = {})
|
|
364
483
|
ensure_same_node(:zunionstore, destination, *keys) do |node|
|
|
365
484
|
node.zunionstore(destination, keys, options)
|
|
366
485
|
end
|
|
367
486
|
end
|
|
368
487
|
|
|
488
|
+
# Set the string value of a hash field.
|
|
369
489
|
def hset(key, field, value)
|
|
370
490
|
node_for(key).hset(key, field, value)
|
|
371
491
|
end
|
|
372
492
|
|
|
493
|
+
# Get the value of a hash field.
|
|
373
494
|
def hget(key, field)
|
|
374
495
|
node_for(key).hget(key, field)
|
|
375
496
|
end
|
|
376
497
|
|
|
498
|
+
# Delete a hash field.
|
|
377
499
|
def hdel(key, field)
|
|
378
500
|
node_for(key).hdel(key, field)
|
|
379
501
|
end
|
|
380
502
|
|
|
503
|
+
# Determine if a hash field exists.
|
|
381
504
|
def hexists(key, field)
|
|
382
505
|
node_for(key).hexists(key, field)
|
|
383
506
|
end
|
|
384
507
|
|
|
508
|
+
# Get the number of fields in a hash.
|
|
385
509
|
def hlen(key)
|
|
386
510
|
node_for(key).hlen(key)
|
|
387
511
|
end
|
|
388
512
|
|
|
513
|
+
# Get all the fields in a hash.
|
|
389
514
|
def hkeys(key)
|
|
390
515
|
node_for(key).hkeys(key)
|
|
391
516
|
end
|
|
392
517
|
|
|
518
|
+
# Get all the values in a hash.
|
|
393
519
|
def hvals(key)
|
|
394
520
|
node_for(key).hvals(key)
|
|
395
521
|
end
|
|
396
522
|
|
|
523
|
+
# Get all the fields and values in a hash.
|
|
397
524
|
def hgetall(key)
|
|
398
525
|
node_for(key).hgetall(key)
|
|
399
526
|
end
|
|
400
527
|
|
|
528
|
+
# Set multiple hash fields to multiple values.
|
|
401
529
|
def hmset(key, *attrs)
|
|
402
530
|
node_for(key).hmset(key, *attrs)
|
|
403
531
|
end
|
|
404
532
|
|
|
533
|
+
def mapped_hmset(key, hash)
|
|
534
|
+
node_for(key).hmset(key, *hash.to_a.flatten)
|
|
535
|
+
end
|
|
536
|
+
|
|
537
|
+
# Get the values of all the given hash fields.
|
|
538
|
+
def hmget(key, *fields)
|
|
539
|
+
node_for(key).hmget(key, *fields)
|
|
540
|
+
end
|
|
541
|
+
|
|
542
|
+
def mapped_hmget(key, *fields)
|
|
543
|
+
Hash[*fields.zip(hmget(key, *fields)).flatten]
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
# Increment the integer value of a hash field by the given number.
|
|
405
547
|
def hincrby(key, field, increment)
|
|
406
548
|
node_for(key).hincrby(key, field, increment)
|
|
407
549
|
end
|
|
408
550
|
|
|
551
|
+
# Sort the elements in a list, set or sorted set.
|
|
409
552
|
def sort(key, options = {})
|
|
410
553
|
keys = [key, options[:by], options[:store], *Array(options[:get])].compact
|
|
411
554
|
|
|
@@ -414,18 +557,32 @@ class Redis
|
|
|
414
557
|
end
|
|
415
558
|
end
|
|
416
559
|
|
|
417
|
-
|
|
560
|
+
# Mark the start of a transaction block.
|
|
561
|
+
def multi
|
|
418
562
|
raise CannotDistribute, :multi
|
|
419
563
|
end
|
|
420
564
|
|
|
565
|
+
# Watch the given keys to determine execution of the MULTI/EXEC block.
|
|
566
|
+
def watch(*keys)
|
|
567
|
+
raise CannotDistribute, :watch
|
|
568
|
+
end
|
|
569
|
+
|
|
570
|
+
# Forget about all watched keys.
|
|
571
|
+
def unwatch
|
|
572
|
+
raise CannotDistribute, :unwatch
|
|
573
|
+
end
|
|
574
|
+
|
|
575
|
+
# Execute all commands issued after MULTI.
|
|
421
576
|
def exec
|
|
422
577
|
raise CannotDistribute, :exec
|
|
423
578
|
end
|
|
424
579
|
|
|
580
|
+
# Discard all commands issued after MULTI.
|
|
425
581
|
def discard
|
|
426
582
|
raise CannotDistribute, :discard
|
|
427
583
|
end
|
|
428
584
|
|
|
585
|
+
# Post a message to a channel.
|
|
429
586
|
def publish(channel, message)
|
|
430
587
|
node_for(channel).publish(channel, message)
|
|
431
588
|
end
|
|
@@ -434,11 +591,13 @@ class Redis
|
|
|
434
591
|
!! @subscribed_node
|
|
435
592
|
end
|
|
436
593
|
|
|
594
|
+
# Stop listening for messages posted to the given channels.
|
|
437
595
|
def unsubscribe(*channels)
|
|
438
596
|
raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed?
|
|
439
597
|
@subscribed_node.unsubscribe(*channels)
|
|
440
598
|
end
|
|
441
599
|
|
|
600
|
+
# Listen for messages published to the given channels.
|
|
442
601
|
def subscribe(channel, *channels, &block)
|
|
443
602
|
if channels.empty?
|
|
444
603
|
@subscribed_node = node_for(channel)
|
|
@@ -451,34 +610,43 @@ class Redis
|
|
|
451
610
|
end
|
|
452
611
|
end
|
|
453
612
|
|
|
613
|
+
# Stop listening for messages posted to channels matching the given
|
|
614
|
+
# patterns.
|
|
454
615
|
def punsubscribe(*channels)
|
|
455
616
|
raise NotImplementedError
|
|
456
617
|
end
|
|
457
618
|
|
|
619
|
+
# Listen for messages published to channels matching the given patterns.
|
|
458
620
|
def psubscribe(*channels, &block)
|
|
459
621
|
raise NotImplementedError
|
|
460
622
|
end
|
|
461
623
|
|
|
624
|
+
# Synchronously save the dataset to disk.
|
|
462
625
|
def save
|
|
463
626
|
on_each_node :save
|
|
464
627
|
end
|
|
465
628
|
|
|
629
|
+
# Asynchronously save the dataset to disk.
|
|
466
630
|
def bgsave
|
|
467
631
|
on_each_node :bgsave
|
|
468
632
|
end
|
|
469
633
|
|
|
634
|
+
# Get the UNIX time stamp of the last successful save to disk.
|
|
470
635
|
def lastsave
|
|
471
636
|
on_each_node :lastsave
|
|
472
637
|
end
|
|
473
638
|
|
|
474
|
-
|
|
475
|
-
|
|
639
|
+
# Get information and statistics about the server.
|
|
640
|
+
def info(cmd = nil)
|
|
641
|
+
on_each_node :info, cmd
|
|
476
642
|
end
|
|
477
643
|
|
|
644
|
+
# Listen for all requests received by the server in real time.
|
|
478
645
|
def monitor
|
|
479
646
|
raise NotImplementedError
|
|
480
647
|
end
|
|
481
648
|
|
|
649
|
+
# Echo the given string.
|
|
482
650
|
def echo(value)
|
|
483
651
|
on_each_node :echo, value
|
|
484
652
|
end
|
|
@@ -487,6 +655,13 @@ class Redis
|
|
|
487
655
|
raise CannotDistribute, :pipelined
|
|
488
656
|
end
|
|
489
657
|
|
|
658
|
+
def inspect
|
|
659
|
+
node_info = nodes.map do |node|
|
|
660
|
+
"#{node.id} (Redis v#{node.info['redis_version']})"
|
|
661
|
+
end
|
|
662
|
+
"#<Redis client v#{Redis::VERSION} connected to #{node_info.join(', ')}>"
|
|
663
|
+
end
|
|
664
|
+
|
|
490
665
|
protected
|
|
491
666
|
|
|
492
667
|
def on_each_node(command, *args)
|
|
@@ -500,7 +675,7 @@ class Redis
|
|
|
500
675
|
end
|
|
501
676
|
|
|
502
677
|
def key_tag(key)
|
|
503
|
-
key[@tag, 1] if @tag
|
|
678
|
+
key.to_s[@tag, 1] if @tag
|
|
504
679
|
end
|
|
505
680
|
|
|
506
681
|
def ensure_same_node(command, *keys)
|
data/lib/redis/pipeline.rb
CHANGED
|
@@ -6,8 +6,29 @@ class Redis
|
|
|
6
6
|
@commands = []
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
+
# Starting with 2.2.1, assume that this method is called with a single
|
|
10
|
+
# array argument. Check its size for backwards compat.
|
|
9
11
|
def call(*args)
|
|
10
|
-
|
|
12
|
+
if args.first.is_a?(Array) && args.size == 1
|
|
13
|
+
command = args.first
|
|
14
|
+
else
|
|
15
|
+
command = args
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
@commands << command
|
|
19
|
+
nil
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Assume that this method is called with a single array argument. No
|
|
23
|
+
# backwards compat here, since it was introduced in 2.2.2.
|
|
24
|
+
def call_without_reply(command)
|
|
25
|
+
@commands.push command
|
|
26
|
+
nil
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def call_pipelined(commands, options = {})
|
|
30
|
+
@commands.concat commands
|
|
31
|
+
nil
|
|
11
32
|
end
|
|
12
33
|
end
|
|
13
34
|
end
|
data/lib/redis/subscribe.rb
CHANGED
|
@@ -4,8 +4,23 @@ class Redis
|
|
|
4
4
|
@client = client
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
+
# Starting with 2.2.1, assume that this method is called with a single
|
|
8
|
+
# array argument. Check its size for backwards compat.
|
|
7
9
|
def call(*args)
|
|
8
|
-
|
|
10
|
+
if args.first.is_a?(Array) && args.size == 1
|
|
11
|
+
command = args.first
|
|
12
|
+
else
|
|
13
|
+
command = args
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
@client.process([command])
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Assume that this method is called with a single array argument. No
|
|
20
|
+
# backwards compat here, since it was introduced in 2.2.2.
|
|
21
|
+
def call_without_reply(command)
|
|
22
|
+
@commands.push command
|
|
23
|
+
nil
|
|
9
24
|
end
|
|
10
25
|
|
|
11
26
|
def subscribe(*channels, &block)
|
|
@@ -17,11 +32,11 @@ class Redis
|
|
|
17
32
|
end
|
|
18
33
|
|
|
19
34
|
def unsubscribe(*channels)
|
|
20
|
-
call
|
|
35
|
+
call [:unsubscribe, *channels]
|
|
21
36
|
end
|
|
22
37
|
|
|
23
38
|
def punsubscribe(*channels)
|
|
24
|
-
call
|
|
39
|
+
call [:punsubscribe, *channels]
|
|
25
40
|
end
|
|
26
41
|
|
|
27
42
|
protected
|
|
@@ -30,7 +45,7 @@ class Redis
|
|
|
30
45
|
sub = Subscription.new(&block)
|
|
31
46
|
|
|
32
47
|
begin
|
|
33
|
-
@client.call_loop(start, *channels) do |line|
|
|
48
|
+
@client.call_loop([start, *channels]) do |line|
|
|
34
49
|
type, *rest = line
|
|
35
50
|
sub.callbacks[type].call(*rest)
|
|
36
51
|
break if type == stop && rest.last == 0
|