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