redis 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +8 -0
- data/CHANGELOG.md +34 -0
- data/README.md +190 -0
- data/Rakefile +194 -79
- 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.rb +612 -156
- data/lib/redis/client.rb +98 -57
- data/lib/redis/connection.rb +9 -134
- 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 +131 -0
- data/lib/redis/connection/synchrony.rb +125 -0
- data/lib/redis/distributed.rb +161 -5
- data/lib/redis/pipeline.rb +6 -0
- data/lib/redis/version.rb +3 -0
- 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 +87 -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 +18 -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 +31 -0
- data/test/distributed_sorting_test.rb +21 -0
- data/test/distributed_test.rb +60 -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 +157 -0
- data/test/lint/hashes.rb +114 -0
- data/test/lint/internals.rb +41 -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 +63 -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 +128 -19
- data/README.markdown +0 -129
@@ -0,0 +1,20 @@
|
|
1
|
+
require "redis"
|
2
|
+
|
3
|
+
worker_processes 3
|
4
|
+
|
5
|
+
# If you set the connection to Redis *before* forking,
|
6
|
+
# you will cause forks to share a file descriptor.
|
7
|
+
#
|
8
|
+
# This causes a concurrency problem by which one fork
|
9
|
+
# can read or write to the socket while others are
|
10
|
+
# performing other operations.
|
11
|
+
#
|
12
|
+
# Most likely you'll be getting ProtocolError exceptions
|
13
|
+
# mentioning a wrong initial byte in the reply.
|
14
|
+
#
|
15
|
+
# Thus we need to connect to Redis after forking the
|
16
|
+
# worker processes.
|
17
|
+
|
18
|
+
after_fork do |server, worker|
|
19
|
+
$redis = Redis.connect
|
20
|
+
end
|
data/lib/redis.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "monitor"
|
2
2
|
|
3
3
|
class Redis
|
4
|
-
VERSION = "2.1.1"
|
5
|
-
|
6
4
|
class ProtocolError < RuntimeError
|
7
5
|
def initialize(reply_type)
|
8
6
|
super(<<-EOS.gsub(/(?:^|\n)\s*/, " "))
|
@@ -15,6 +13,12 @@ class Redis
|
|
15
13
|
end
|
16
14
|
end
|
17
15
|
|
16
|
+
module DisableThreadSafety
|
17
|
+
def synchronize
|
18
|
+
yield
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
18
22
|
def self.deprecate(message, trace = caller[0])
|
19
23
|
$stderr.puts "\n#{message} (in #{trace})"
|
20
24
|
end
|
@@ -44,414 +48,770 @@ class Redis
|
|
44
48
|
Thread.current[:redis] = redis
|
45
49
|
end
|
46
50
|
|
51
|
+
include MonitorMixin
|
52
|
+
|
47
53
|
def initialize(options = {})
|
48
|
-
|
49
|
-
|
54
|
+
@client = Client.new(options)
|
55
|
+
|
56
|
+
if options[:thread_safe] == false
|
57
|
+
# Override #synchronize
|
58
|
+
extend DisableThreadSafety
|
50
59
|
else
|
51
|
-
|
60
|
+
# Monitor#initialize
|
61
|
+
super()
|
52
62
|
end
|
53
63
|
end
|
54
64
|
|
65
|
+
# Run code without the client reconnecting
|
66
|
+
def without_reconnect(&block)
|
67
|
+
synchronize do
|
68
|
+
@client.without_reconnect(&block)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Authenticate to the server.
|
55
73
|
def auth(password)
|
56
|
-
|
74
|
+
synchronize do
|
75
|
+
@client.call(:auth, password)
|
76
|
+
end
|
57
77
|
end
|
58
78
|
|
79
|
+
# Change the selected database for the current connection.
|
59
80
|
def select(db)
|
60
|
-
|
61
|
-
|
81
|
+
synchronize do
|
82
|
+
@client.db = db
|
83
|
+
@client.call(:select, db)
|
84
|
+
end
|
62
85
|
end
|
63
86
|
|
87
|
+
# Get information and statistics about the server.
|
64
88
|
def info
|
65
|
-
|
89
|
+
synchronize do
|
90
|
+
reply = @client.call(:info)
|
91
|
+
|
92
|
+
if reply.kind_of?(String)
|
93
|
+
Hash[*reply.split(/:|\r\n/).grep(/^[^#]/)]
|
94
|
+
else
|
95
|
+
reply
|
96
|
+
end
|
97
|
+
end
|
66
98
|
end
|
67
99
|
|
68
100
|
def config(action, *args)
|
69
|
-
|
70
|
-
|
71
|
-
|
101
|
+
synchronize do
|
102
|
+
reply = @client.call(:config, action, *args)
|
103
|
+
|
104
|
+
if reply.kind_of?(Array) && action == :get
|
105
|
+
Hash[*reply]
|
106
|
+
else
|
107
|
+
reply
|
108
|
+
end
|
109
|
+
end
|
72
110
|
end
|
73
111
|
|
112
|
+
# Remove all keys from the current database.
|
74
113
|
def flushdb
|
75
|
-
|
114
|
+
synchronize do
|
115
|
+
@client.call(:flushdb)
|
116
|
+
end
|
76
117
|
end
|
77
118
|
|
119
|
+
# Remove all keys from all databases.
|
78
120
|
def flushall
|
79
|
-
|
121
|
+
synchronize do
|
122
|
+
@client.call(:flushall)
|
123
|
+
end
|
80
124
|
end
|
81
125
|
|
126
|
+
# Synchronously save the dataset to disk.
|
82
127
|
def save
|
83
|
-
|
128
|
+
synchronize do
|
129
|
+
@client.call(:save)
|
130
|
+
end
|
84
131
|
end
|
85
132
|
|
133
|
+
# Asynchronously save the dataset to disk.
|
86
134
|
def bgsave
|
87
|
-
|
135
|
+
synchronize do
|
136
|
+
@client.call(:bgsave)
|
137
|
+
end
|
88
138
|
end
|
89
139
|
|
140
|
+
# Asynchronously rewrite the append-only file.
|
90
141
|
def bgrewriteaof
|
91
|
-
|
142
|
+
synchronize do
|
143
|
+
@client.call(:bgrewriteaof)
|
144
|
+
end
|
92
145
|
end
|
93
146
|
|
147
|
+
# Get the value of a key.
|
94
148
|
def get(key)
|
95
|
-
|
149
|
+
synchronize do
|
150
|
+
@client.call(:get, key)
|
151
|
+
end
|
96
152
|
end
|
97
153
|
|
154
|
+
# Returns the bit value at offset in the string value stored at key.
|
155
|
+
def getbit(key, offset)
|
156
|
+
synchronize do
|
157
|
+
@client.call(:getbit, key, offset)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Get a substring of the string stored at a key.
|
162
|
+
def getrange(key, start, stop)
|
163
|
+
synchronize do
|
164
|
+
@client.call(:getrange, key, start, stop)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
# Set the string value of a key and return its old value.
|
98
169
|
def getset(key, value)
|
99
|
-
|
170
|
+
synchronize do
|
171
|
+
@client.call(:getset, key, value)
|
172
|
+
end
|
100
173
|
end
|
101
174
|
|
175
|
+
# Get the values of all the given keys.
|
102
176
|
def mget(*keys)
|
103
|
-
|
177
|
+
synchronize do
|
178
|
+
@client.call(:mget, *keys)
|
179
|
+
end
|
104
180
|
end
|
105
181
|
|
182
|
+
# Append a value to a key.
|
106
183
|
def append(key, value)
|
107
|
-
|
184
|
+
synchronize do
|
185
|
+
@client.call(:append, key, value)
|
186
|
+
end
|
108
187
|
end
|
109
188
|
|
110
189
|
def substr(key, start, stop)
|
111
|
-
|
190
|
+
synchronize do
|
191
|
+
@client.call(:substr, key, start, stop)
|
192
|
+
end
|
112
193
|
end
|
113
194
|
|
195
|
+
# Get the length of the value stored in a key.
|
114
196
|
def strlen(key)
|
115
|
-
|
197
|
+
synchronize do
|
198
|
+
@client.call(:strlen, key)
|
199
|
+
end
|
116
200
|
end
|
117
201
|
|
202
|
+
# Get all the fields and values in a hash.
|
118
203
|
def hgetall(key)
|
119
|
-
|
204
|
+
synchronize do
|
205
|
+
reply = @client.call(:hgetall, key)
|
206
|
+
|
207
|
+
if reply.kind_of?(Array)
|
208
|
+
Hash[*reply]
|
209
|
+
else
|
210
|
+
reply
|
211
|
+
end
|
212
|
+
end
|
120
213
|
end
|
121
214
|
|
215
|
+
# Get the value of a hash field.
|
122
216
|
def hget(key, field)
|
123
|
-
|
217
|
+
synchronize do
|
218
|
+
@client.call(:hget, key, field)
|
219
|
+
end
|
124
220
|
end
|
125
221
|
|
222
|
+
# Delete a hash field.
|
126
223
|
def hdel(key, field)
|
127
|
-
|
224
|
+
synchronize do
|
225
|
+
@client.call(:hdel, key, field)
|
226
|
+
end
|
128
227
|
end
|
129
228
|
|
229
|
+
# Get all the fields in a hash.
|
130
230
|
def hkeys(key)
|
131
|
-
|
231
|
+
synchronize do
|
232
|
+
@client.call(:hkeys, key)
|
233
|
+
end
|
132
234
|
end
|
133
235
|
|
236
|
+
# Find all keys matching the given pattern.
|
134
237
|
def keys(pattern = "*")
|
135
|
-
|
238
|
+
synchronize do
|
239
|
+
reply = @client.call(:keys, pattern)
|
240
|
+
|
241
|
+
if reply.kind_of?(String)
|
242
|
+
reply.split(" ")
|
243
|
+
else
|
244
|
+
reply
|
245
|
+
end
|
246
|
+
end
|
136
247
|
end
|
137
248
|
|
249
|
+
# Return a random key from the keyspace.
|
138
250
|
def randomkey
|
139
|
-
|
251
|
+
synchronize do
|
252
|
+
@client.call(:randomkey)
|
253
|
+
end
|
140
254
|
end
|
141
255
|
|
256
|
+
# Echo the given string.
|
142
257
|
def echo(value)
|
143
|
-
|
258
|
+
synchronize do
|
259
|
+
@client.call(:echo, value)
|
260
|
+
end
|
144
261
|
end
|
145
262
|
|
263
|
+
# Ping the server.
|
146
264
|
def ping
|
147
|
-
|
265
|
+
synchronize do
|
266
|
+
@client.call(:ping)
|
267
|
+
end
|
148
268
|
end
|
149
269
|
|
270
|
+
# Get the UNIX time stamp of the last successful save to disk.
|
150
271
|
def lastsave
|
151
|
-
|
272
|
+
synchronize do
|
273
|
+
@client.call(:lastsave)
|
274
|
+
end
|
152
275
|
end
|
153
276
|
|
277
|
+
# Return the number of keys in the selected database.
|
154
278
|
def dbsize
|
155
|
-
|
279
|
+
synchronize do
|
280
|
+
@client.call(:dbsize)
|
281
|
+
end
|
156
282
|
end
|
157
283
|
|
284
|
+
# Determine if a key exists.
|
158
285
|
def exists(key)
|
159
|
-
|
286
|
+
synchronize do
|
287
|
+
_bool @client.call(:exists, key)
|
288
|
+
end
|
160
289
|
end
|
161
290
|
|
291
|
+
# Get the length of a list.
|
162
292
|
def llen(key)
|
163
|
-
|
293
|
+
synchronize do
|
294
|
+
@client.call(:llen, key)
|
295
|
+
end
|
164
296
|
end
|
165
297
|
|
298
|
+
# Get a range of elements from a list.
|
166
299
|
def lrange(key, start, stop)
|
167
|
-
|
300
|
+
synchronize do
|
301
|
+
@client.call(:lrange, key, start, stop)
|
302
|
+
end
|
168
303
|
end
|
169
304
|
|
305
|
+
# Trim a list to the specified range.
|
170
306
|
def ltrim(key, start, stop)
|
171
|
-
|
307
|
+
synchronize do
|
308
|
+
@client.call(:ltrim, key, start, stop)
|
309
|
+
end
|
172
310
|
end
|
173
311
|
|
312
|
+
# Get an element from a list by its index.
|
174
313
|
def lindex(key, index)
|
175
|
-
|
314
|
+
synchronize do
|
315
|
+
@client.call(:lindex, key, index)
|
316
|
+
end
|
176
317
|
end
|
177
318
|
|
319
|
+
# Insert an element before or after another element in a list.
|
178
320
|
def linsert(key, where, pivot, value)
|
179
|
-
|
321
|
+
synchronize do
|
322
|
+
@client.call(:linsert, key, where, pivot, value)
|
323
|
+
end
|
180
324
|
end
|
181
325
|
|
326
|
+
# Set the value of an element in a list by its index.
|
182
327
|
def lset(key, index, value)
|
183
|
-
|
328
|
+
synchronize do
|
329
|
+
@client.call(:lset, key, index, value)
|
330
|
+
end
|
184
331
|
end
|
185
332
|
|
333
|
+
# Remove elements from a list.
|
186
334
|
def lrem(key, count, value)
|
187
|
-
|
335
|
+
synchronize do
|
336
|
+
@client.call(:lrem, key, count, value)
|
337
|
+
end
|
188
338
|
end
|
189
339
|
|
340
|
+
# Append a value to a list.
|
190
341
|
def rpush(key, value)
|
191
|
-
|
342
|
+
synchronize do
|
343
|
+
@client.call(:rpush, key, value)
|
344
|
+
end
|
192
345
|
end
|
193
346
|
|
347
|
+
# Append a value to a list, only if the list exists.
|
194
348
|
def rpushx(key, value)
|
195
|
-
|
349
|
+
synchronize do
|
350
|
+
@client.call(:rpushx, key, value)
|
351
|
+
end
|
196
352
|
end
|
197
353
|
|
354
|
+
# Prepend a value to a list.
|
198
355
|
def lpush(key, value)
|
199
|
-
|
356
|
+
synchronize do
|
357
|
+
@client.call(:lpush, key, value)
|
358
|
+
end
|
200
359
|
end
|
201
360
|
|
361
|
+
# Prepend a value to a list, only if the list exists.
|
202
362
|
def lpushx(key, value)
|
203
|
-
|
363
|
+
synchronize do
|
364
|
+
@client.call(:lpushx, key, value)
|
365
|
+
end
|
204
366
|
end
|
205
367
|
|
368
|
+
# Remove and get the last element in a list.
|
206
369
|
def rpop(key)
|
207
|
-
|
370
|
+
synchronize do
|
371
|
+
@client.call(:rpop, key)
|
372
|
+
end
|
208
373
|
end
|
209
374
|
|
375
|
+
# Remove and get the first element in a list, or block until one is available.
|
210
376
|
def blpop(*args)
|
211
|
-
|
377
|
+
synchronize do
|
378
|
+
@client.call_without_timeout(:blpop, *args)
|
379
|
+
end
|
212
380
|
end
|
213
381
|
|
382
|
+
# Remove and get the last element in a list, or block until one is available.
|
214
383
|
def brpop(*args)
|
215
|
-
|
384
|
+
synchronize do
|
385
|
+
@client.call_without_timeout(:brpop, *args)
|
386
|
+
end
|
387
|
+
end
|
388
|
+
|
389
|
+
# Pop a value from a list, push it to another list and return it; or block
|
390
|
+
# until one is available.
|
391
|
+
def brpoplpush(source, destination, timeout)
|
392
|
+
synchronize do
|
393
|
+
@client.call_without_timeout(:brpoplpush, source, destination, timeout)
|
394
|
+
end
|
216
395
|
end
|
217
396
|
|
397
|
+
# Remove the last element in a list, append it to another list and return it.
|
218
398
|
def rpoplpush(source, destination)
|
219
|
-
|
399
|
+
synchronize do
|
400
|
+
@client.call(:rpoplpush, source, destination)
|
401
|
+
end
|
220
402
|
end
|
221
403
|
|
404
|
+
# Remove and get the first element in a list.
|
222
405
|
def lpop(key)
|
223
|
-
|
406
|
+
synchronize do
|
407
|
+
@client.call(:lpop, key)
|
408
|
+
end
|
224
409
|
end
|
225
410
|
|
411
|
+
# Get all the members in a set.
|
226
412
|
def smembers(key)
|
227
|
-
|
413
|
+
synchronize do
|
414
|
+
@client.call(:smembers, key)
|
415
|
+
end
|
228
416
|
end
|
229
417
|
|
418
|
+
# Determine if a given value is a member of a set.
|
230
419
|
def sismember(key, member)
|
231
|
-
|
420
|
+
synchronize do
|
421
|
+
_bool @client.call(:sismember, key, member)
|
422
|
+
end
|
232
423
|
end
|
233
424
|
|
425
|
+
# Add a member to a set.
|
234
426
|
def sadd(key, value)
|
235
|
-
|
427
|
+
synchronize do
|
428
|
+
_bool @client.call(:sadd, key, value)
|
429
|
+
end
|
236
430
|
end
|
237
431
|
|
432
|
+
# Remove a member from a set.
|
238
433
|
def srem(key, value)
|
239
|
-
|
434
|
+
synchronize do
|
435
|
+
_bool @client.call(:srem, key, value)
|
436
|
+
end
|
240
437
|
end
|
241
438
|
|
439
|
+
# Move a member from one set to another.
|
242
440
|
def smove(source, destination, member)
|
243
|
-
|
441
|
+
synchronize do
|
442
|
+
_bool @client.call(:smove, source, destination, member)
|
443
|
+
end
|
244
444
|
end
|
245
445
|
|
446
|
+
# Remove and return a random member from a set.
|
246
447
|
def spop(key)
|
247
|
-
|
448
|
+
synchronize do
|
449
|
+
@client.call(:spop, key)
|
450
|
+
end
|
248
451
|
end
|
249
452
|
|
453
|
+
# Get the number of members in a set.
|
250
454
|
def scard(key)
|
251
|
-
|
455
|
+
synchronize do
|
456
|
+
@client.call(:scard, key)
|
457
|
+
end
|
252
458
|
end
|
253
459
|
|
460
|
+
# Intersect multiple sets.
|
254
461
|
def sinter(*keys)
|
255
|
-
|
462
|
+
synchronize do
|
463
|
+
@client.call(:sinter, *keys)
|
464
|
+
end
|
256
465
|
end
|
257
466
|
|
467
|
+
# Intersect multiple sets and store the resulting set in a key.
|
258
468
|
def sinterstore(destination, *keys)
|
259
|
-
|
469
|
+
synchronize do
|
470
|
+
@client.call(:sinterstore, destination, *keys)
|
471
|
+
end
|
260
472
|
end
|
261
473
|
|
474
|
+
# Add multiple sets.
|
262
475
|
def sunion(*keys)
|
263
|
-
|
476
|
+
synchronize do
|
477
|
+
@client.call(:sunion, *keys)
|
478
|
+
end
|
264
479
|
end
|
265
480
|
|
481
|
+
# Add multiple sets and store the resulting set in a key.
|
266
482
|
def sunionstore(destination, *keys)
|
267
|
-
|
483
|
+
synchronize do
|
484
|
+
@client.call(:sunionstore, destination, *keys)
|
485
|
+
end
|
268
486
|
end
|
269
487
|
|
488
|
+
# Subtract multiple sets.
|
270
489
|
def sdiff(*keys)
|
271
|
-
|
490
|
+
synchronize do
|
491
|
+
@client.call(:sdiff, *keys)
|
492
|
+
end
|
272
493
|
end
|
273
494
|
|
495
|
+
# Subtract multiple sets and store the resulting set in a key.
|
274
496
|
def sdiffstore(destination, *keys)
|
275
|
-
|
497
|
+
synchronize do
|
498
|
+
@client.call(:sdiffstore, destination, *keys)
|
499
|
+
end
|
276
500
|
end
|
277
501
|
|
502
|
+
# Get a random member from a set.
|
278
503
|
def srandmember(key)
|
279
|
-
|
504
|
+
synchronize do
|
505
|
+
@client.call(:srandmember, key)
|
506
|
+
end
|
280
507
|
end
|
281
508
|
|
509
|
+
# Add a member to a sorted set, or update its score if it already exists.
|
282
510
|
def zadd(key, score, member)
|
283
|
-
|
511
|
+
synchronize do
|
512
|
+
_bool @client.call(:zadd, key, score, member)
|
513
|
+
end
|
284
514
|
end
|
285
515
|
|
516
|
+
# Determine the index of a member in a sorted set.
|
286
517
|
def zrank(key, member)
|
287
|
-
|
518
|
+
synchronize do
|
519
|
+
@client.call(:zrank, key, member)
|
520
|
+
end
|
288
521
|
end
|
289
522
|
|
523
|
+
# Determine the index of a member in a sorted set, with scores ordered from
|
524
|
+
# high to low.
|
290
525
|
def zrevrank(key, member)
|
291
|
-
|
526
|
+
synchronize do
|
527
|
+
@client.call(:zrevrank, key, member)
|
528
|
+
end
|
292
529
|
end
|
293
530
|
|
531
|
+
# Increment the score of a member in a sorted set.
|
294
532
|
def zincrby(key, increment, member)
|
295
|
-
|
533
|
+
synchronize do
|
534
|
+
@client.call(:zincrby, key, increment, member)
|
535
|
+
end
|
296
536
|
end
|
297
537
|
|
538
|
+
# Get the number of members in a sorted set.
|
298
539
|
def zcard(key)
|
299
|
-
|
540
|
+
synchronize do
|
541
|
+
@client.call(:zcard, key)
|
542
|
+
end
|
300
543
|
end
|
301
544
|
|
545
|
+
# Return a range of members in a sorted set, by index.
|
302
546
|
def zrange(key, start, stop, options = {})
|
303
547
|
command = CommandOptions.new(options) do |c|
|
548
|
+
c.bool :withscores
|
304
549
|
c.bool :with_scores
|
305
550
|
end
|
306
551
|
|
307
|
-
|
552
|
+
synchronize do
|
553
|
+
@client.call(:zrange, key, start, stop, *command.to_a)
|
554
|
+
end
|
308
555
|
end
|
309
556
|
|
557
|
+
# Return a range of members in a sorted set, by score.
|
310
558
|
def zrangebyscore(key, min, max, options = {})
|
311
559
|
command = CommandOptions.new(options) do |c|
|
312
560
|
c.splat :limit
|
561
|
+
c.bool :withscores
|
313
562
|
c.bool :with_scores
|
314
563
|
end
|
315
564
|
|
316
|
-
|
565
|
+
synchronize do
|
566
|
+
@client.call(:zrangebyscore, key, min, max, *command.to_a)
|
567
|
+
end
|
317
568
|
end
|
318
569
|
|
570
|
+
# Count the members in a sorted set with scores within the given values.
|
319
571
|
def zcount(key, start, stop)
|
320
|
-
|
572
|
+
synchronize do
|
573
|
+
@client.call(:zcount, key, start, stop)
|
574
|
+
end
|
321
575
|
end
|
322
576
|
|
577
|
+
# Return a range of members in a sorted set, by index, with scores ordered
|
578
|
+
# from high to low.
|
323
579
|
def zrevrange(key, start, stop, options = {})
|
324
580
|
command = CommandOptions.new(options) do |c|
|
581
|
+
c.bool :withscores
|
325
582
|
c.bool :with_scores
|
326
583
|
end
|
327
584
|
|
328
|
-
|
585
|
+
synchronize do
|
586
|
+
@client.call(:zrevrange, key, start, stop, *command.to_a)
|
587
|
+
end
|
329
588
|
end
|
330
589
|
|
590
|
+
# Return a range of members in a sorted set, by score, with scores ordered
|
591
|
+
# from high to low.
|
592
|
+
def zrevrangebyscore(key, max, min, options = {})
|
593
|
+
command = CommandOptions.new(options) do |c|
|
594
|
+
c.splat :limit
|
595
|
+
c.bool :withscores
|
596
|
+
c.bool :with_scores
|
597
|
+
end
|
598
|
+
|
599
|
+
synchronize do
|
600
|
+
@client.call(:zrevrangebyscore, key, max, min, *command.to_a)
|
601
|
+
end
|
602
|
+
end
|
603
|
+
|
604
|
+
# Remove all members in a sorted set within the given scores.
|
331
605
|
def zremrangebyscore(key, min, max)
|
332
|
-
|
606
|
+
synchronize do
|
607
|
+
@client.call(:zremrangebyscore, key, min, max)
|
608
|
+
end
|
333
609
|
end
|
334
610
|
|
611
|
+
# Remove all members in a sorted set within the given indexes.
|
335
612
|
def zremrangebyrank(key, start, stop)
|
336
|
-
|
613
|
+
synchronize do
|
614
|
+
@client.call(:zremrangebyrank, key, start, stop)
|
615
|
+
end
|
337
616
|
end
|
338
617
|
|
618
|
+
# Get the score associated with the given member in a sorted set.
|
339
619
|
def zscore(key, member)
|
340
|
-
|
620
|
+
synchronize do
|
621
|
+
@client.call(:zscore, key, member)
|
622
|
+
end
|
341
623
|
end
|
342
624
|
|
625
|
+
# Remove a member from a sorted set.
|
343
626
|
def zrem(key, member)
|
344
|
-
|
627
|
+
synchronize do
|
628
|
+
_bool @client.call(:zrem, key, member)
|
629
|
+
end
|
345
630
|
end
|
346
631
|
|
632
|
+
# Intersect multiple sorted sets and store the resulting sorted set in a new
|
633
|
+
# key.
|
347
634
|
def zinterstore(destination, keys, options = {})
|
348
635
|
command = CommandOptions.new(options) do |c|
|
349
636
|
c.splat :weights
|
350
637
|
c.value :aggregate
|
351
638
|
end
|
352
639
|
|
353
|
-
|
640
|
+
synchronize do
|
641
|
+
@client.call(:zinterstore, destination, keys.size, *(keys + command.to_a))
|
642
|
+
end
|
354
643
|
end
|
355
644
|
|
645
|
+
# Add multiple sorted sets and store the resulting sorted set in a new key.
|
356
646
|
def zunionstore(destination, keys, options = {})
|
357
647
|
command = CommandOptions.new(options) do |c|
|
358
648
|
c.splat :weights
|
359
649
|
c.value :aggregate
|
360
650
|
end
|
361
651
|
|
362
|
-
|
652
|
+
synchronize do
|
653
|
+
@client.call(:zunionstore, destination, keys.size, *(keys + command.to_a))
|
654
|
+
end
|
363
655
|
end
|
364
656
|
|
657
|
+
# Move a key to another database.
|
365
658
|
def move(key, db)
|
366
|
-
|
659
|
+
synchronize do
|
660
|
+
_bool @client.call(:move, key, db)
|
661
|
+
end
|
367
662
|
end
|
368
663
|
|
664
|
+
# Set the value of a key, only if the key does not exist.
|
369
665
|
def setnx(key, value)
|
370
|
-
|
666
|
+
synchronize do
|
667
|
+
_bool @client.call(:setnx, key, value)
|
668
|
+
end
|
371
669
|
end
|
372
670
|
|
671
|
+
# Delete a key.
|
373
672
|
def del(*keys)
|
374
|
-
|
673
|
+
synchronize do
|
674
|
+
@client.call(:del, *keys)
|
675
|
+
end
|
375
676
|
end
|
376
677
|
|
678
|
+
# Rename a key.
|
377
679
|
def rename(old_name, new_name)
|
378
|
-
|
680
|
+
synchronize do
|
681
|
+
@client.call(:rename, old_name, new_name)
|
682
|
+
end
|
379
683
|
end
|
380
684
|
|
685
|
+
# Rename a key, only if the new key does not exist.
|
381
686
|
def renamenx(old_name, new_name)
|
382
|
-
|
687
|
+
synchronize do
|
688
|
+
_bool @client.call(:renamenx, old_name, new_name)
|
689
|
+
end
|
383
690
|
end
|
384
691
|
|
692
|
+
# Set a key's time to live in seconds.
|
385
693
|
def expire(key, seconds)
|
386
|
-
|
694
|
+
synchronize do
|
695
|
+
_bool @client.call(:expire, key, seconds)
|
696
|
+
end
|
387
697
|
end
|
388
698
|
|
699
|
+
# Remove the expiration from a key.
|
389
700
|
def persist(key)
|
390
|
-
|
701
|
+
synchronize do
|
702
|
+
_bool @client.call(:persist, key)
|
703
|
+
end
|
391
704
|
end
|
392
705
|
|
706
|
+
# Get the time to live for a key.
|
393
707
|
def ttl(key)
|
394
|
-
|
708
|
+
synchronize do
|
709
|
+
@client.call(:ttl, key)
|
710
|
+
end
|
395
711
|
end
|
396
712
|
|
713
|
+
# Set the expiration for a key as a UNIX timestamp.
|
397
714
|
def expireat(key, unix_time)
|
398
|
-
|
715
|
+
synchronize do
|
716
|
+
_bool @client.call(:expireat, key, unix_time)
|
717
|
+
end
|
399
718
|
end
|
400
719
|
|
720
|
+
# Set the string value of a hash field.
|
401
721
|
def hset(key, field, value)
|
402
|
-
|
722
|
+
synchronize do
|
723
|
+
_bool @client.call(:hset, key, field, value)
|
724
|
+
end
|
403
725
|
end
|
404
726
|
|
727
|
+
# Set the value of a hash field, only if the field does not exist.
|
405
728
|
def hsetnx(key, field, value)
|
406
|
-
|
729
|
+
synchronize do
|
730
|
+
_bool @client.call(:hsetnx, key, field, value)
|
731
|
+
end
|
407
732
|
end
|
408
733
|
|
734
|
+
# Set multiple hash fields to multiple values.
|
409
735
|
def hmset(key, *attrs)
|
410
|
-
|
736
|
+
synchronize do
|
737
|
+
@client.call(:hmset, key, *attrs)
|
738
|
+
end
|
411
739
|
end
|
412
740
|
|
413
741
|
def mapped_hmset(key, hash)
|
414
742
|
hmset(key, *hash.to_a.flatten)
|
415
743
|
end
|
416
744
|
|
745
|
+
# Get the values of all the given hash fields.
|
417
746
|
def hmget(key, *fields)
|
418
|
-
|
747
|
+
synchronize do
|
748
|
+
@client.call(:hmget, key, *fields)
|
749
|
+
end
|
419
750
|
end
|
420
751
|
|
421
752
|
def mapped_hmget(key, *fields)
|
422
|
-
|
753
|
+
reply = hmget(key, *fields)
|
754
|
+
|
755
|
+
if reply.kind_of?(Array)
|
756
|
+
Hash[*fields.zip(reply).flatten]
|
757
|
+
else
|
758
|
+
reply
|
759
|
+
end
|
423
760
|
end
|
424
761
|
|
762
|
+
# Get the number of fields in a hash.
|
425
763
|
def hlen(key)
|
426
|
-
|
764
|
+
synchronize do
|
765
|
+
@client.call(:hlen, key)
|
766
|
+
end
|
427
767
|
end
|
428
768
|
|
769
|
+
# Get all the values in a hash.
|
429
770
|
def hvals(key)
|
430
|
-
|
771
|
+
synchronize do
|
772
|
+
@client.call(:hvals, key)
|
773
|
+
end
|
431
774
|
end
|
432
775
|
|
776
|
+
# Increment the integer value of a hash field by the given number.
|
433
777
|
def hincrby(key, field, increment)
|
434
|
-
|
778
|
+
synchronize do
|
779
|
+
@client.call(:hincrby, key, field, increment)
|
780
|
+
end
|
435
781
|
end
|
436
782
|
|
783
|
+
# Discard all commands issued after MULTI.
|
437
784
|
def discard
|
438
|
-
|
785
|
+
synchronize do
|
786
|
+
@client.call(:discard)
|
787
|
+
end
|
439
788
|
end
|
440
789
|
|
790
|
+
# Determine if a hash field exists.
|
441
791
|
def hexists(key, field)
|
442
|
-
|
792
|
+
synchronize do
|
793
|
+
_bool @client.call(:hexists, key, field)
|
794
|
+
end
|
443
795
|
end
|
444
796
|
|
797
|
+
# Listen for all requests received by the server in real time.
|
445
798
|
def monitor(&block)
|
446
|
-
|
799
|
+
synchronize do
|
800
|
+
@client.call_loop(:monitor, &block)
|
801
|
+
end
|
447
802
|
end
|
448
803
|
|
449
804
|
def debug(*args)
|
450
|
-
|
805
|
+
synchronize do
|
806
|
+
@client.call(:debug, *args)
|
807
|
+
end
|
451
808
|
end
|
452
809
|
|
810
|
+
# Internal command used for replication.
|
453
811
|
def sync
|
454
|
-
|
812
|
+
synchronize do
|
813
|
+
@client.call(:sync)
|
814
|
+
end
|
455
815
|
end
|
456
816
|
|
457
817
|
def [](key)
|
@@ -462,24 +822,50 @@ class Redis
|
|
462
822
|
set(key, value)
|
463
823
|
end
|
464
824
|
|
825
|
+
# Set the string value of a key.
|
465
826
|
def set(key, value)
|
466
|
-
|
827
|
+
synchronize do
|
828
|
+
@client.call(:set, key, value)
|
829
|
+
end
|
467
830
|
end
|
468
831
|
|
832
|
+
# Sets or clears the bit at offset in the string value stored at key.
|
833
|
+
def setbit(key, offset, value)
|
834
|
+
synchronize do
|
835
|
+
@client.call(:setbit, key, offset, value)
|
836
|
+
end
|
837
|
+
end
|
838
|
+
|
839
|
+
# Set the value and expiration of a key.
|
469
840
|
def setex(key, ttl, value)
|
470
|
-
|
841
|
+
synchronize do
|
842
|
+
@client.call(:setex, key, ttl, value)
|
843
|
+
end
|
844
|
+
end
|
845
|
+
|
846
|
+
# Overwrite part of a string at key starting at the specified offset.
|
847
|
+
def setrange(key, offset, value)
|
848
|
+
synchronize do
|
849
|
+
@client.call(:setrange, key, offset, value)
|
850
|
+
end
|
471
851
|
end
|
472
852
|
|
853
|
+
# Set multiple keys to multiple values.
|
473
854
|
def mset(*args)
|
474
|
-
|
855
|
+
synchronize do
|
856
|
+
@client.call(:mset, *args)
|
857
|
+
end
|
475
858
|
end
|
476
859
|
|
477
860
|
def mapped_mset(hash)
|
478
861
|
mset(*hash.to_a.flatten)
|
479
862
|
end
|
480
863
|
|
864
|
+
# Set multiple keys to multiple values, only if none of the keys exist.
|
481
865
|
def msetnx(*args)
|
482
|
-
|
866
|
+
synchronize do
|
867
|
+
@client.call(:msetnx, *args)
|
868
|
+
end
|
483
869
|
end
|
484
870
|
|
485
871
|
def mapped_msetnx(hash)
|
@@ -487,9 +873,16 @@ class Redis
|
|
487
873
|
end
|
488
874
|
|
489
875
|
def mapped_mget(*keys)
|
490
|
-
|
876
|
+
reply = mget(*keys)
|
877
|
+
|
878
|
+
if reply.kind_of?(Array)
|
879
|
+
Hash[*keys.zip(reply).flatten]
|
880
|
+
else
|
881
|
+
reply
|
882
|
+
end
|
491
883
|
end
|
492
884
|
|
885
|
+
# Sort the elements in a list, set or sorted set.
|
493
886
|
def sort(key, options = {})
|
494
887
|
command = CommandOptions.new(options) do |c|
|
495
888
|
c.value :by
|
@@ -499,115 +892,181 @@ class Redis
|
|
499
892
|
c.value :store
|
500
893
|
end
|
501
894
|
|
502
|
-
|
895
|
+
synchronize do
|
896
|
+
@client.call(:sort, key, *command.to_a)
|
897
|
+
end
|
503
898
|
end
|
504
899
|
|
900
|
+
# Increment the integer value of a key by one.
|
505
901
|
def incr(key)
|
506
|
-
|
902
|
+
synchronize do
|
903
|
+
@client.call(:incr, key)
|
904
|
+
end
|
507
905
|
end
|
508
906
|
|
907
|
+
# Increment the integer value of a key by the given number.
|
509
908
|
def incrby(key, increment)
|
510
|
-
|
909
|
+
synchronize do
|
910
|
+
@client.call(:incrby, key, increment)
|
911
|
+
end
|
511
912
|
end
|
512
913
|
|
914
|
+
# Decrement the integer value of a key by one.
|
513
915
|
def decr(key)
|
514
|
-
|
916
|
+
synchronize do
|
917
|
+
@client.call(:decr, key)
|
918
|
+
end
|
515
919
|
end
|
516
920
|
|
921
|
+
# Decrement the integer value of a key by the given number.
|
517
922
|
def decrby(key, decrement)
|
518
|
-
|
923
|
+
synchronize do
|
924
|
+
@client.call(:decrby, key, decrement)
|
925
|
+
end
|
519
926
|
end
|
520
927
|
|
928
|
+
# Determine the type stored at key.
|
521
929
|
def type(key)
|
522
|
-
|
930
|
+
synchronize do
|
931
|
+
@client.call(:type, key)
|
932
|
+
end
|
523
933
|
end
|
524
934
|
|
935
|
+
# Close the connection.
|
525
936
|
def quit
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
937
|
+
synchronize do
|
938
|
+
begin
|
939
|
+
@client.call(:quit)
|
940
|
+
rescue Errno::ECONNRESET
|
941
|
+
ensure
|
942
|
+
@client.disconnect
|
943
|
+
end
|
944
|
+
end
|
530
945
|
end
|
531
946
|
|
947
|
+
# Synchronously save the dataset to disk and then shut down the server.
|
532
948
|
def shutdown
|
533
|
-
|
949
|
+
synchronize do
|
950
|
+
@client.call(:shutdown)
|
951
|
+
end
|
534
952
|
end
|
535
953
|
|
954
|
+
# Make the server a slave of another instance, or promote it as master.
|
536
955
|
def slaveof(host, port)
|
537
|
-
|
956
|
+
synchronize do
|
957
|
+
@client.call(:slaveof, host, port)
|
958
|
+
end
|
538
959
|
end
|
539
960
|
|
540
|
-
def pipelined
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
961
|
+
def pipelined(options = {})
|
962
|
+
synchronize do
|
963
|
+
begin
|
964
|
+
original, @client = @client, Pipeline.new
|
965
|
+
yield
|
966
|
+
original.call_pipelined(@client.commands, options) unless @client.commands.empty?
|
967
|
+
ensure
|
968
|
+
@client = original
|
969
|
+
end
|
970
|
+
end
|
546
971
|
end
|
547
972
|
|
973
|
+
# Watch the given keys to determine execution of the MULTI/EXEC block.
|
548
974
|
def watch(*keys)
|
549
|
-
|
975
|
+
synchronize do
|
976
|
+
@client.call(:watch, *keys)
|
977
|
+
end
|
550
978
|
end
|
551
979
|
|
980
|
+
# Forget about all watched keys.
|
552
981
|
def unwatch
|
553
|
-
|
982
|
+
synchronize do
|
983
|
+
@client.call(:unwatch)
|
984
|
+
end
|
554
985
|
end
|
555
986
|
|
987
|
+
# Execute all commands issued after MULTI.
|
556
988
|
def exec
|
557
|
-
|
989
|
+
synchronize do
|
990
|
+
@client.call(:exec)
|
991
|
+
end
|
558
992
|
end
|
559
993
|
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
994
|
+
# Mark the start of a transaction block.
|
995
|
+
def multi
|
996
|
+
synchronize do
|
997
|
+
if !block_given?
|
998
|
+
@client.call :multi
|
999
|
+
else
|
1000
|
+
result = pipelined(:raise => false) do
|
1001
|
+
multi
|
1002
|
+
yield(self)
|
1003
|
+
exec
|
1004
|
+
end
|
1005
|
+
|
1006
|
+
result.last
|
1007
|
+
end
|
570
1008
|
end
|
571
|
-
|
572
|
-
exec
|
573
1009
|
end
|
574
1010
|
|
1011
|
+
# Post a message to a channel.
|
575
1012
|
def publish(channel, message)
|
576
|
-
|
1013
|
+
synchronize do
|
1014
|
+
@client.call(:publish, channel, message)
|
1015
|
+
end
|
577
1016
|
end
|
578
1017
|
|
579
1018
|
def subscribed?
|
580
|
-
|
1019
|
+
synchronize do
|
1020
|
+
@client.kind_of? SubscribedClient
|
1021
|
+
end
|
581
1022
|
end
|
582
1023
|
|
1024
|
+
# Stop listening for messages posted to the given channels.
|
583
1025
|
def unsubscribe(*channels)
|
584
|
-
|
585
|
-
|
1026
|
+
synchronize do
|
1027
|
+
raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed?
|
1028
|
+
@client.unsubscribe(*channels)
|
1029
|
+
end
|
586
1030
|
end
|
587
1031
|
|
1032
|
+
# Stop listening for messages posted to channels matching the given patterns.
|
588
1033
|
def punsubscribe(*channels)
|
589
|
-
|
590
|
-
|
1034
|
+
synchronize do
|
1035
|
+
raise RuntimeError, "Can't unsubscribe if not subscribed." unless subscribed?
|
1036
|
+
@client.punsubscribe(*channels)
|
1037
|
+
end
|
591
1038
|
end
|
592
1039
|
|
1040
|
+
# Listen for messages published to the given channels.
|
593
1041
|
def subscribe(*channels, &block)
|
594
|
-
|
1042
|
+
synchronize do
|
1043
|
+
subscription(:subscribe, channels, block)
|
1044
|
+
end
|
595
1045
|
end
|
596
1046
|
|
1047
|
+
# Listen for messages published to channels matching the given patterns.
|
597
1048
|
def psubscribe(*channels, &block)
|
598
|
-
|
1049
|
+
synchronize do
|
1050
|
+
subscription(:psubscribe, channels, block)
|
1051
|
+
end
|
599
1052
|
end
|
600
1053
|
|
601
1054
|
def id
|
602
|
-
|
1055
|
+
synchronize do
|
1056
|
+
@client.id
|
1057
|
+
end
|
603
1058
|
end
|
604
1059
|
|
605
1060
|
def inspect
|
606
|
-
|
1061
|
+
synchronize do
|
1062
|
+
"#<Redis client v#{Redis::VERSION} connected to #{id} (Redis v#{info["redis_version"]})>"
|
1063
|
+
end
|
607
1064
|
end
|
608
1065
|
|
609
1066
|
def method_missing(command, *args)
|
610
|
-
|
1067
|
+
synchronize do
|
1068
|
+
@client.call(command, *args)
|
1069
|
+
end
|
611
1070
|
end
|
612
1071
|
|
613
1072
|
class CommandOptions
|
@@ -652,10 +1111,6 @@ private
|
|
652
1111
|
value == 1
|
653
1112
|
end
|
654
1113
|
|
655
|
-
def _array(value)
|
656
|
-
value.kind_of?(Array) ? value : value.split(" ")
|
657
|
-
end
|
658
|
-
|
659
1114
|
def subscription(method, channels, block)
|
660
1115
|
return @client.call(method, *channels) if subscribed?
|
661
1116
|
|
@@ -669,7 +1124,8 @@ private
|
|
669
1124
|
|
670
1125
|
end
|
671
1126
|
|
672
|
-
require "redis/
|
1127
|
+
require "redis/version"
|
1128
|
+
require "redis/connection"
|
673
1129
|
require "redis/client"
|
674
1130
|
require "redis/pipeline"
|
675
1131
|
require "redis/subscribe"
|