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.
Files changed (81) hide show
  1. data/.gitignore +8 -0
  2. data/CHANGELOG.md +49 -0
  3. data/README.md +208 -0
  4. data/Rakefile +183 -73
  5. data/TODO.md +4 -0
  6. data/benchmarking/logging.rb +62 -0
  7. data/benchmarking/pipeline.rb +51 -0
  8. data/benchmarking/speed.rb +21 -0
  9. data/benchmarking/suite.rb +24 -0
  10. data/benchmarking/thread_safety.rb +38 -0
  11. data/benchmarking/worker.rb +71 -0
  12. data/examples/basic.rb +15 -0
  13. data/examples/dist_redis.rb +43 -0
  14. data/examples/incr-decr.rb +17 -0
  15. data/examples/list.rb +26 -0
  16. data/examples/pubsub.rb +31 -0
  17. data/examples/sets.rb +36 -0
  18. data/examples/unicorn/config.ru +3 -0
  19. data/examples/unicorn/unicorn.rb +20 -0
  20. data/lib/redis/client.rb +149 -165
  21. data/lib/redis/connection/command_helper.rb +45 -0
  22. data/lib/redis/connection/hiredis.rb +49 -0
  23. data/lib/redis/connection/registry.rb +12 -0
  24. data/lib/redis/connection/ruby.rb +135 -0
  25. data/lib/redis/connection/synchrony.rb +129 -0
  26. data/lib/redis/connection.rb +9 -0
  27. data/lib/redis/distributed.rb +182 -7
  28. data/lib/redis/pipeline.rb +22 -1
  29. data/lib/redis/subscribe.rb +19 -4
  30. data/lib/redis/version.rb +3 -0
  31. data/lib/redis.rb +715 -155
  32. data/redis.gemspec +24 -0
  33. data/test/commands_on_hashes_test.rb +32 -0
  34. data/test/commands_on_lists_test.rb +60 -0
  35. data/test/commands_on_sets_test.rb +78 -0
  36. data/test/commands_on_sorted_sets_test.rb +109 -0
  37. data/test/commands_on_strings_test.rb +80 -0
  38. data/test/commands_on_value_types_test.rb +88 -0
  39. data/test/connection_handling_test.rb +88 -0
  40. data/test/db/.gitignore +1 -0
  41. data/test/distributed_blocking_commands_test.rb +53 -0
  42. data/test/distributed_commands_on_hashes_test.rb +12 -0
  43. data/test/distributed_commands_on_lists_test.rb +24 -0
  44. data/test/distributed_commands_on_sets_test.rb +85 -0
  45. data/test/distributed_commands_on_strings_test.rb +50 -0
  46. data/test/distributed_commands_on_value_types_test.rb +73 -0
  47. data/test/distributed_commands_requiring_clustering_test.rb +148 -0
  48. data/test/distributed_connection_handling_test.rb +25 -0
  49. data/test/distributed_internals_test.rb +27 -0
  50. data/test/distributed_key_tags_test.rb +53 -0
  51. data/test/distributed_persistence_control_commands_test.rb +24 -0
  52. data/test/distributed_publish_subscribe_test.rb +101 -0
  53. data/test/distributed_remote_server_control_commands_test.rb +43 -0
  54. data/test/distributed_sorting_test.rb +21 -0
  55. data/test/distributed_test.rb +59 -0
  56. data/test/distributed_transactions_test.rb +34 -0
  57. data/test/encoding_test.rb +16 -0
  58. data/test/error_replies_test.rb +53 -0
  59. data/test/helper.rb +145 -0
  60. data/test/internals_test.rb +160 -0
  61. data/test/lint/hashes.rb +114 -0
  62. data/test/lint/internals.rb +37 -0
  63. data/test/lint/lists.rb +93 -0
  64. data/test/lint/sets.rb +66 -0
  65. data/test/lint/sorted_sets.rb +167 -0
  66. data/test/lint/strings.rb +137 -0
  67. data/test/lint/value_types.rb +84 -0
  68. data/test/persistence_control_commands_test.rb +22 -0
  69. data/test/pipelining_commands_test.rb +123 -0
  70. data/test/publish_subscribe_test.rb +158 -0
  71. data/test/redis_mock.rb +80 -0
  72. data/test/remote_server_control_commands_test.rb +82 -0
  73. data/test/sorting_test.rb +44 -0
  74. data/test/synchrony_driver.rb +57 -0
  75. data/test/test.conf +8 -0
  76. data/test/thread_safety_test.rb +30 -0
  77. data/test/transactions_test.rb +100 -0
  78. data/test/unknown_commands_test.rb +14 -0
  79. data/test/url_param_test.rb +60 -0
  80. metadata +130 -22
  81. data/README.markdown +0 -120
@@ -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
- def del(*keys)
58
- on_each_node(:del, *keys)
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
- def multi(&block)
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
- def info
475
- on_each_node :info
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)
@@ -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
- @commands << args
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
@@ -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
- @client.process(args)
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(:unsubscribe, *channels)
35
+ call [:unsubscribe, *channels]
21
36
  end
22
37
 
23
38
  def punsubscribe(*channels)
24
- call(:punsubscribe, *channels)
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
@@ -0,0 +1,3 @@
1
+ class Redis
2
+ VERSION = "2.2.1"
3
+ end