redis 3.2.2 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of redis might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.travis.yml +9 -3
- data/CHANGELOG.md +14 -0
- data/README.md +85 -3
- data/lib/redis.rb +117 -74
- data/lib/redis/client.rb +32 -14
- data/lib/redis/connection/hiredis.rb +3 -1
- data/lib/redis/connection/ruby.rb +56 -2
- data/lib/redis/connection/synchrony.rb +11 -2
- data/lib/redis/subscribe.rb +10 -2
- data/lib/redis/version.rb +1 -1
- data/redis.gemspec +2 -2
- data/test/client_test.rb +59 -0
- data/test/connection_handling_test.rb +27 -0
- data/test/distributed_internals_test.rb +1 -1
- data/test/lint/blocking_commands.rb +1 -1
- data/test/lint/sorted_sets.rb +4 -4
- data/test/publish_subscribe_test.rb +28 -0
- data/test/ssl_test.rb +66 -0
- data/test/support/redis_mock.rb +13 -2
- data/test/support/ssl/gen_certs.sh +31 -0
- data/test/support/ssl/trusted-ca.crt +25 -0
- data/test/support/ssl/trusted-ca.key +27 -0
- data/test/support/ssl/trusted-cert.crt +81 -0
- data/test/support/ssl/trusted-cert.key +28 -0
- data/test/support/ssl/untrusted-ca.crt +26 -0
- data/test/support/ssl/untrusted-ca.key +27 -0
- data/test/support/ssl/untrusted-cert.crt +82 -0
- data/test/support/ssl/untrusted-cert.key +28 -0
- data/test/thread_safety_test.rb +30 -0
- metadata +39 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6ab43fd7b8221a41ea88facf6051b6c7b94e87bf
|
4
|
+
data.tar.gz: 333fb1bbd2de6cd74db7cfd40542c979d92a6fbd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3f734315d527b2b92eeb1a6bff2089b583a06784f01fa411f68d4ad23cf9bdb5ae753d6da69a570014ac5d207cc765eb70107f8781c9e432457a7f81ef48fb98
|
7
|
+
data.tar.gz: 686e1a0b28c573d7342335a52fc14d5636f2e1e32e8dba0adab663283e9d6fcc6acfd5d8b100b365ee54905a77a7c3a555c3c87917ef3a77b2689c8ff5afe927
|
data/.travis.yml
CHANGED
@@ -6,8 +6,10 @@ rvm:
|
|
6
6
|
- 2.0
|
7
7
|
- 2.1
|
8
8
|
- 2.2
|
9
|
+
- 2.3.0
|
9
10
|
- jruby-18mode
|
10
11
|
- jruby-19mode
|
12
|
+
- jruby-9.0.5.0
|
11
13
|
- rbx-2
|
12
14
|
|
13
15
|
gemfile: ".travis/Gemfile"
|
@@ -37,6 +39,9 @@ matrix:
|
|
37
39
|
- rvm: jruby-19mode
|
38
40
|
gemfile: .travis/Gemfile
|
39
41
|
env: conn=hiredis REDIS_BRANCH=2.8
|
42
|
+
- rvm: jruby-9.0.5.0
|
43
|
+
gemfile: .travis/Gemfile
|
44
|
+
env: conn=hiredis REDIS_BRANCH=2.8
|
40
45
|
|
41
46
|
# synchrony
|
42
47
|
- rvm: 1.8.7
|
@@ -48,12 +53,13 @@ matrix:
|
|
48
53
|
- rvm: jruby-19mode
|
49
54
|
gemfile: .travis/Gemfile
|
50
55
|
env: conn=synchrony REDIS_BRANCH=2.8
|
56
|
+
- rvm: jruby-9.0.5.0
|
57
|
+
gemfile: .travis/Gemfile
|
58
|
+
env: conn=synchrony REDIS_BRANCH=2.8
|
51
59
|
allow_failures:
|
52
60
|
- rvm: rbx-2
|
53
61
|
|
54
62
|
notifications:
|
55
63
|
irc:
|
56
64
|
- irc.freenode.net#redis-rb
|
57
|
-
email:
|
58
|
-
- damian.janowski@gmail.com
|
59
|
-
- pcnoordhuis@gmail.com
|
65
|
+
email: false
|
data/CHANGELOG.md
CHANGED
@@ -12,6 +12,20 @@
|
|
12
12
|
security updates in June of 2013; continuing to support it would prevent
|
13
13
|
the use of newer features of Ruby.
|
14
14
|
|
15
|
+
# 3.3.0
|
16
|
+
|
17
|
+
* Added support for SSL/TLS. Redis doesn't support SSL natively, so you still
|
18
|
+
need to run a terminating proxy on Redis' side. See #496.
|
19
|
+
|
20
|
+
* Added `read_timeout` and `write_timeout` options. See #437, #482.
|
21
|
+
|
22
|
+
* Added support for pub/sub with timeouts. See #329.
|
23
|
+
|
24
|
+
* Added `Redis#call`, `Redis#queue` and `Redis#commit` as a more minimal API to
|
25
|
+
the client.
|
26
|
+
|
27
|
+
* Deprecated `Redis#disconnect!` in favor of `Redis#close`.
|
28
|
+
|
15
29
|
# 3.2.2
|
16
30
|
|
17
31
|
* Added support for `ZADD` options `NX`, `XX`, `CH`, `INCR`. See #547.
|
data/README.md
CHANGED
@@ -29,7 +29,7 @@ To install **redis-rb**, run the following command:
|
|
29
29
|
gem install redis
|
30
30
|
```
|
31
31
|
|
32
|
-
Or if you are using **bundler**, add
|
32
|
+
Or if you are using **bundler**, add
|
33
33
|
|
34
34
|
```
|
35
35
|
gem 'redis', '~>3.2'
|
@@ -222,6 +222,86 @@ end
|
|
222
222
|
|
223
223
|
See lib/redis/errors.rb for information about what exceptions are possible.
|
224
224
|
|
225
|
+
## Timeouts
|
226
|
+
|
227
|
+
The client allows you to configure connect, read, and write timeouts.
|
228
|
+
Passing a single `timeout` option will set all three values:
|
229
|
+
|
230
|
+
```ruby
|
231
|
+
Redis.new(:timeout => 1)
|
232
|
+
```
|
233
|
+
|
234
|
+
But you can use specific values for each of them:
|
235
|
+
|
236
|
+
```ruby
|
237
|
+
Redis.new(
|
238
|
+
:connect_timeout => 0.2,
|
239
|
+
:read_timeout => 1.0,
|
240
|
+
:write_timeout => 0.5
|
241
|
+
)
|
242
|
+
```
|
243
|
+
|
244
|
+
All timeout values are specified in seconds.
|
245
|
+
|
246
|
+
When using pub/sub, you can subscribe to a channel using a timeout as well:
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
redis.subscribe_with_timeout(5, "news") do |on|
|
250
|
+
on.message do |channel, message|
|
251
|
+
# ...
|
252
|
+
end
|
253
|
+
end
|
254
|
+
```
|
255
|
+
|
256
|
+
If no message is received after 5 seconds, the client will unsubscribe.
|
257
|
+
|
258
|
+
|
259
|
+
## SSL/TLS Support
|
260
|
+
|
261
|
+
This library supports natively terminating client side SSL/TLS connections
|
262
|
+
when talking to Redis via a server-side proxy such as [stunnel], [hitch],
|
263
|
+
or [ghostunnel].
|
264
|
+
|
265
|
+
To enable SSL support, pass the `:ssl => :true` option when configuring the
|
266
|
+
Redis client, or pass in `:url => "rediss://..."` (like HTTPS for Redis).
|
267
|
+
You will also need to pass in an `:ssl_params => { ... }` hash used to
|
268
|
+
configure the `OpenSSL::SSL::SSLContext` object used for the connection:
|
269
|
+
|
270
|
+
```ruby
|
271
|
+
redis = Redis.new(
|
272
|
+
:url => "rediss://:p4ssw0rd@10.0.1.1:6381/15",
|
273
|
+
:ssl_params => {
|
274
|
+
:ca_file => "/path/to/ca.crt"
|
275
|
+
}
|
276
|
+
)
|
277
|
+
```
|
278
|
+
|
279
|
+
The options given to `:ssl_params` are passed directly to the
|
280
|
+
`OpenSSL::SSL::SSLContext#set_params` method and can be any valid attribute
|
281
|
+
of the SSL context. Please see the [OpenSSL::SSL::SSLContext documentation]
|
282
|
+
for all of the available attributes.
|
283
|
+
|
284
|
+
Here is an example of passing in params that can be used for SSL client
|
285
|
+
certificate authentication (a.k.a. mutual TLS):
|
286
|
+
|
287
|
+
```ruby
|
288
|
+
redis = Redis.new(
|
289
|
+
:url => "rediss://:p4ssw0rd@10.0.1.1:6381/15",
|
290
|
+
:ssl_params => {
|
291
|
+
:ca_file => "/path/to/ca.crt",
|
292
|
+
:cert => OpenSSL::X509::Certificate.new(File.read("client.crt")),
|
293
|
+
:key => OpenSSL::PKey::RSA.new(File.read("client.key"))
|
294
|
+
}
|
295
|
+
)
|
296
|
+
```
|
297
|
+
|
298
|
+
[stunnel]: https://www.stunnel.org/
|
299
|
+
[hitch]: https://hitch-tls.org/
|
300
|
+
[ghostunnel]: https://github.com/square/ghostunnel
|
301
|
+
[OpenSSL::SSL::SSLContext documentation]: http://ruby-doc.org/stdlib-2.3.0/libdoc/openssl/rdoc/OpenSSL/SSL/SSLContext.html
|
302
|
+
|
303
|
+
*NOTE:* SSL is only supported by the default "Ruby" driver
|
304
|
+
|
225
305
|
|
226
306
|
## Expert-Mode Options
|
227
307
|
|
@@ -298,9 +378,11 @@ This library is tested using [Travis][travis-home], where it is tested
|
|
298
378
|
against the following interpreters and drivers:
|
299
379
|
|
300
380
|
* MRI 1.8.7 (drivers: ruby, hiredis)
|
301
|
-
* MRI 1.9.2 (drivers: ruby, hiredis, synchrony)
|
302
381
|
* MRI 1.9.3 (drivers: ruby, hiredis, synchrony)
|
303
|
-
* MRI 2.0
|
382
|
+
* MRI 2.0 (drivers: ruby, hiredis, synchrony)
|
383
|
+
* MRI 2.1 (drivers: ruby, hiredis, synchrony)
|
384
|
+
* MRI 2.2 (drivers: ruby, hiredis, synchrony)
|
385
|
+
* MRI 2.3 (drivers: ruby, hiredis, synchrony)
|
304
386
|
* JRuby 1.7 (1.8 mode) (drivers: ruby)
|
305
387
|
* JRuby 1.7 (1.9 mode) (drivers: ruby)
|
306
388
|
|
data/lib/redis.rb
CHANGED
@@ -49,6 +49,7 @@ class Redis
|
|
49
49
|
def initialize(options = {})
|
50
50
|
@options = options.dup
|
51
51
|
@original_client = @client = Client.new(options)
|
52
|
+
@queue = Hash.new { |h, k| h[k] = [] }
|
52
53
|
|
53
54
|
super() # Monitor#initialize
|
54
55
|
end
|
@@ -75,9 +76,48 @@ class Redis
|
|
75
76
|
end
|
76
77
|
|
77
78
|
# Disconnect the client as quickly and silently as possible.
|
78
|
-
def
|
79
|
+
def close
|
79
80
|
@original_client.disconnect
|
80
81
|
end
|
82
|
+
alias disconnect! close
|
83
|
+
|
84
|
+
# Sends a command to Redis and returns its reply.
|
85
|
+
#
|
86
|
+
# Replies are converted to Ruby objects according to the RESP protocol, so
|
87
|
+
# you can expect a Ruby array, integer or nil when Redis sends one. Higher
|
88
|
+
# level transformations, such as converting an array of pairs into a Ruby
|
89
|
+
# hash, are up to consumers.
|
90
|
+
#
|
91
|
+
# Redis error replies are raised as Ruby exceptions.
|
92
|
+
def call(*command)
|
93
|
+
synchronize do |client|
|
94
|
+
client.call(command)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Queues a command for pipelining.
|
99
|
+
#
|
100
|
+
# Commands in the queue are executed with the Redis#commit method.
|
101
|
+
#
|
102
|
+
# See http://redis.io/topics/pipelining for more details.
|
103
|
+
#
|
104
|
+
def queue(*command)
|
105
|
+
@queue[Thread.current.object_id] << command
|
106
|
+
end
|
107
|
+
|
108
|
+
# Sends all commands in the queue.
|
109
|
+
#
|
110
|
+
# See http://redis.io/topics/pipelining for more details.
|
111
|
+
#
|
112
|
+
def commit
|
113
|
+
synchronize do |client|
|
114
|
+
begin
|
115
|
+
client.call_pipelined(@queue[Thread.current.object_id])
|
116
|
+
ensure
|
117
|
+
@queue.delete(Thread.current.object_id)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
81
121
|
|
82
122
|
# Authenticate to the server.
|
83
123
|
#
|
@@ -161,7 +201,7 @@ class Redis
|
|
161
201
|
synchronize do |client|
|
162
202
|
client.call([:config, action] + args) do |reply|
|
163
203
|
if reply.kind_of?(Array) && action == :get
|
164
|
-
|
204
|
+
Hashify.call(reply)
|
165
205
|
else
|
166
206
|
reply
|
167
207
|
end
|
@@ -320,7 +360,7 @@ class Redis
|
|
320
360
|
# @return [Boolean] whether the timeout was removed or not
|
321
361
|
def persist(key)
|
322
362
|
synchronize do |client|
|
323
|
-
client.call([:persist, key], &
|
363
|
+
client.call([:persist, key], &Boolify)
|
324
364
|
end
|
325
365
|
end
|
326
366
|
|
@@ -331,7 +371,7 @@ class Redis
|
|
331
371
|
# @return [Boolean] whether the timeout was set or not
|
332
372
|
def expire(key, seconds)
|
333
373
|
synchronize do |client|
|
334
|
-
client.call([:expire, key, seconds], &
|
374
|
+
client.call([:expire, key, seconds], &Boolify)
|
335
375
|
end
|
336
376
|
end
|
337
377
|
|
@@ -342,7 +382,7 @@ class Redis
|
|
342
382
|
# @return [Boolean] whether the timeout was set or not
|
343
383
|
def expireat(key, unix_time)
|
344
384
|
synchronize do |client|
|
345
|
-
client.call([:expireat, key, unix_time], &
|
385
|
+
client.call([:expireat, key, unix_time], &Boolify)
|
346
386
|
end
|
347
387
|
end
|
348
388
|
|
@@ -371,7 +411,7 @@ class Redis
|
|
371
411
|
# @return [Boolean] whether the timeout was set or not
|
372
412
|
def pexpire(key, milliseconds)
|
373
413
|
synchronize do |client|
|
374
|
-
client.call([:pexpire, key, milliseconds], &
|
414
|
+
client.call([:pexpire, key, milliseconds], &Boolify)
|
375
415
|
end
|
376
416
|
end
|
377
417
|
|
@@ -382,7 +422,7 @@ class Redis
|
|
382
422
|
# @return [Boolean] whether the timeout was set or not
|
383
423
|
def pexpireat(key, ms_unix_time)
|
384
424
|
synchronize do |client|
|
385
|
-
client.call([:pexpireat, key, ms_unix_time], &
|
425
|
+
client.call([:pexpireat, key, ms_unix_time], &Boolify)
|
386
426
|
end
|
387
427
|
end
|
388
428
|
|
@@ -461,7 +501,7 @@ class Redis
|
|
461
501
|
# @return [Boolean]
|
462
502
|
def exists(key)
|
463
503
|
synchronize do |client|
|
464
|
-
client.call([:exists, key], &
|
504
|
+
client.call([:exists, key], &Boolify)
|
465
505
|
end
|
466
506
|
end
|
467
507
|
|
@@ -502,7 +542,7 @@ class Redis
|
|
502
542
|
# @return [Boolean] whether the key was moved or not
|
503
543
|
def move(key, db)
|
504
544
|
synchronize do |client|
|
505
|
-
client.call([:move, key, db], &
|
545
|
+
client.call([:move, key, db], &Boolify)
|
506
546
|
end
|
507
547
|
end
|
508
548
|
|
@@ -539,7 +579,7 @@ class Redis
|
|
539
579
|
# @return [Boolean] whether the key was renamed or not
|
540
580
|
def renamenx(old_name, new_name)
|
541
581
|
synchronize do |client|
|
542
|
-
client.call([:renamenx, old_name, new_name], &
|
582
|
+
client.call([:renamenx, old_name, new_name], &Boolify)
|
543
583
|
end
|
544
584
|
end
|
545
585
|
|
@@ -678,7 +718,7 @@ class Redis
|
|
678
718
|
# @return [Float] value after incrementing it
|
679
719
|
def incrbyfloat(key, increment)
|
680
720
|
synchronize do |client|
|
681
|
-
client.call([:incrbyfloat, key, increment], &
|
721
|
+
client.call([:incrbyfloat, key, increment], &Floatify)
|
682
722
|
end
|
683
723
|
end
|
684
724
|
|
@@ -709,7 +749,7 @@ class Redis
|
|
709
749
|
|
710
750
|
synchronize do |client|
|
711
751
|
if nx || xx
|
712
|
-
client.call([:set, key, value.to_s] + args, &
|
752
|
+
client.call([:set, key, value.to_s] + args, &BoolifySet)
|
713
753
|
else
|
714
754
|
client.call([:set, key, value.to_s] + args)
|
715
755
|
end
|
@@ -749,7 +789,7 @@ class Redis
|
|
749
789
|
# @return [Boolean] whether the key was set or not
|
750
790
|
def setnx(key, value)
|
751
791
|
synchronize do |client|
|
752
|
-
client.call([:setnx, key, value.to_s], &
|
792
|
+
client.call([:setnx, key, value.to_s], &Boolify)
|
753
793
|
end
|
754
794
|
end
|
755
795
|
|
@@ -795,7 +835,7 @@ class Redis
|
|
795
835
|
# @see #mapped_msetnx
|
796
836
|
def msetnx(*args)
|
797
837
|
synchronize do |client|
|
798
|
-
client.call([:msetnx] + args, &
|
838
|
+
client.call([:msetnx] + args, &Boolify)
|
799
839
|
end
|
800
840
|
end
|
801
841
|
|
@@ -844,7 +884,7 @@ class Redis
|
|
844
884
|
# Get the values of all the given keys.
|
845
885
|
#
|
846
886
|
# @example
|
847
|
-
# redis.mapped_mget("key1", "
|
887
|
+
# redis.mapped_mget("key1", "key2")
|
848
888
|
# # => { "key1" => "v1", "key2" => "v2" }
|
849
889
|
#
|
850
890
|
# @param [Array<String>] keys array of keys
|
@@ -1268,7 +1308,7 @@ class Redis
|
|
1268
1308
|
reply
|
1269
1309
|
else
|
1270
1310
|
# Single argument: return boolean
|
1271
|
-
|
1311
|
+
Boolify.call(reply)
|
1272
1312
|
end
|
1273
1313
|
end
|
1274
1314
|
end
|
@@ -1290,7 +1330,7 @@ class Redis
|
|
1290
1330
|
reply
|
1291
1331
|
else
|
1292
1332
|
# Single argument: return boolean
|
1293
|
-
|
1333
|
+
Boolify.call(reply)
|
1294
1334
|
end
|
1295
1335
|
end
|
1296
1336
|
end
|
@@ -1329,7 +1369,7 @@ class Redis
|
|
1329
1369
|
# @return [Boolean]
|
1330
1370
|
def smove(source, destination, member)
|
1331
1371
|
synchronize do |client|
|
1332
|
-
client.call([:smove, source, destination, member], &
|
1372
|
+
client.call([:smove, source, destination, member], &Boolify)
|
1333
1373
|
end
|
1334
1374
|
end
|
1335
1375
|
|
@@ -1340,7 +1380,7 @@ class Redis
|
|
1340
1380
|
# @return [Boolean]
|
1341
1381
|
def sismember(key, member)
|
1342
1382
|
synchronize do |client|
|
1343
|
-
client.call([:sismember, key, member], &
|
1383
|
+
client.call([:sismember, key, member], &Boolify)
|
1344
1384
|
end
|
1345
1385
|
end
|
1346
1386
|
|
@@ -1483,10 +1523,10 @@ class Redis
|
|
1483
1523
|
synchronize do |client|
|
1484
1524
|
if args.size == 1 && args[0].is_a?(Array)
|
1485
1525
|
# Variadic: return float if INCR, integer if !INCR
|
1486
|
-
client.call([:zadd, key] + zadd_options + args[0], &(incr ?
|
1526
|
+
client.call([:zadd, key] + zadd_options + args[0], &(incr ? Floatify : nil))
|
1487
1527
|
elsif args.size == 2
|
1488
1528
|
# Single pair: return float if INCR, boolean if !INCR
|
1489
|
-
client.call([:zadd, key] + zadd_options + args, &(incr ?
|
1529
|
+
client.call([:zadd, key] + zadd_options + args, &(incr ? Floatify : Boolify))
|
1490
1530
|
else
|
1491
1531
|
raise ArgumentError, "wrong number of arguments"
|
1492
1532
|
end
|
@@ -1505,7 +1545,7 @@ class Redis
|
|
1505
1545
|
# @return [Float] score of the member after incrementing it
|
1506
1546
|
def zincrby(key, increment, member)
|
1507
1547
|
synchronize do |client|
|
1508
|
-
client.call([:zincrby, key, increment, member], &
|
1548
|
+
client.call([:zincrby, key, increment, member], &Floatify)
|
1509
1549
|
end
|
1510
1550
|
end
|
1511
1551
|
|
@@ -1534,7 +1574,7 @@ class Redis
|
|
1534
1574
|
reply
|
1535
1575
|
else
|
1536
1576
|
# Single argument: return boolean
|
1537
|
-
|
1577
|
+
Boolify.call(reply)
|
1538
1578
|
end
|
1539
1579
|
end
|
1540
1580
|
end
|
@@ -1551,7 +1591,7 @@ class Redis
|
|
1551
1591
|
# @return [Float] score of the member
|
1552
1592
|
def zscore(key, member)
|
1553
1593
|
synchronize do |client|
|
1554
|
-
client.call([:zscore, key, member], &
|
1594
|
+
client.call([:zscore, key, member], &Floatify)
|
1555
1595
|
end
|
1556
1596
|
end
|
1557
1597
|
|
@@ -1580,7 +1620,7 @@ class Redis
|
|
1580
1620
|
|
1581
1621
|
if with_scores
|
1582
1622
|
args << "WITHSCORES"
|
1583
|
-
block =
|
1623
|
+
block = FloatifyPairs
|
1584
1624
|
end
|
1585
1625
|
|
1586
1626
|
synchronize do |client|
|
@@ -1606,7 +1646,7 @@ class Redis
|
|
1606
1646
|
|
1607
1647
|
if with_scores
|
1608
1648
|
args << "WITHSCORES"
|
1609
|
-
block =
|
1649
|
+
block = FloatifyPairs
|
1610
1650
|
end
|
1611
1651
|
|
1612
1652
|
synchronize do |client|
|
@@ -1744,7 +1784,7 @@ class Redis
|
|
1744
1784
|
|
1745
1785
|
if with_scores
|
1746
1786
|
args << "WITHSCORES"
|
1747
|
-
block =
|
1787
|
+
block = FloatifyPairs
|
1748
1788
|
end
|
1749
1789
|
|
1750
1790
|
limit = options[:limit]
|
@@ -1776,7 +1816,7 @@ class Redis
|
|
1776
1816
|
|
1777
1817
|
if with_scores
|
1778
1818
|
args << ["WITHSCORES"]
|
1779
|
-
block =
|
1819
|
+
block = FloatifyPairs
|
1780
1820
|
end
|
1781
1821
|
|
1782
1822
|
limit = options[:limit]
|
@@ -1906,7 +1946,7 @@ class Redis
|
|
1906
1946
|
# @return [Boolean] whether or not the field was **added** to the hash
|
1907
1947
|
def hset(key, field, value)
|
1908
1948
|
synchronize do |client|
|
1909
|
-
client.call([:hset, key, field, value], &
|
1949
|
+
client.call([:hset, key, field, value], &Boolify)
|
1910
1950
|
end
|
1911
1951
|
end
|
1912
1952
|
|
@@ -1918,7 +1958,7 @@ class Redis
|
|
1918
1958
|
# @return [Boolean] whether or not the field was **added** to the hash
|
1919
1959
|
def hsetnx(key, field, value)
|
1920
1960
|
synchronize do |client|
|
1921
|
-
client.call([:hsetnx, key, field, value], &
|
1961
|
+
client.call([:hsetnx, key, field, value], &Boolify)
|
1922
1962
|
end
|
1923
1963
|
end
|
1924
1964
|
|
@@ -2021,7 +2061,7 @@ class Redis
|
|
2021
2061
|
# @return [Boolean] whether or not the field exists in the hash
|
2022
2062
|
def hexists(key, field)
|
2023
2063
|
synchronize do |client|
|
2024
|
-
client.call([:hexists, key, field], &
|
2064
|
+
client.call([:hexists, key, field], &Boolify)
|
2025
2065
|
end
|
2026
2066
|
end
|
2027
2067
|
|
@@ -2045,7 +2085,7 @@ class Redis
|
|
2045
2085
|
# @return [Float] value of the field after incrementing it
|
2046
2086
|
def hincrbyfloat(key, field, increment)
|
2047
2087
|
synchronize do |client|
|
2048
|
-
client.call([:hincrbyfloat, key, field, increment], &
|
2088
|
+
client.call([:hincrbyfloat, key, field, increment], &Floatify)
|
2049
2089
|
end
|
2050
2090
|
end
|
2051
2091
|
|
@@ -2075,7 +2115,7 @@ class Redis
|
|
2075
2115
|
# @return [Hash<String, String>]
|
2076
2116
|
def hgetall(key)
|
2077
2117
|
synchronize do |client|
|
2078
|
-
client.call([:hgetall, key], &
|
2118
|
+
client.call([:hgetall, key], &Hashify)
|
2079
2119
|
end
|
2080
2120
|
end
|
2081
2121
|
|
@@ -2095,7 +2135,14 @@ class Redis
|
|
2095
2135
|
# Listen for messages published to the given channels.
|
2096
2136
|
def subscribe(*channels, &block)
|
2097
2137
|
synchronize do |client|
|
2098
|
-
_subscription(:subscribe, channels, block)
|
2138
|
+
_subscription(:subscribe, 0, channels, block)
|
2139
|
+
end
|
2140
|
+
end
|
2141
|
+
|
2142
|
+
# Listen for messages published to the given channels. Throw a timeout error if there is no messages for a timeout period.
|
2143
|
+
def subscribe_with_timeout(timeout, *channels, &block)
|
2144
|
+
synchronize do |client|
|
2145
|
+
_subscription(:subscribe_with_timeout, timeout, channels, block)
|
2099
2146
|
end
|
2100
2147
|
end
|
2101
2148
|
|
@@ -2110,7 +2157,14 @@ class Redis
|
|
2110
2157
|
# Listen for messages published to channels matching the given patterns.
|
2111
2158
|
def psubscribe(*channels, &block)
|
2112
2159
|
synchronize do |client|
|
2113
|
-
_subscription(:psubscribe, channels, block)
|
2160
|
+
_subscription(:psubscribe, 0, channels, block)
|
2161
|
+
end
|
2162
|
+
end
|
2163
|
+
|
2164
|
+
# Listen for messages published to channels matching the given patterns. Throw a timeout error if there is no messages for a timeout period.
|
2165
|
+
def psubscribe_with_timeout(timeout, *channels, &block)
|
2166
|
+
synchronize do |client|
|
2167
|
+
_subscription(:psubscribe_with_timeout, timeout, channels, block)
|
2114
2168
|
end
|
2115
2169
|
end
|
2116
2170
|
|
@@ -2312,7 +2366,7 @@ class Redis
|
|
2312
2366
|
arg = args.first
|
2313
2367
|
|
2314
2368
|
client.call([:script, :exists, arg]) do |reply|
|
2315
|
-
reply = reply.map { |r|
|
2369
|
+
reply = reply.map { |r| Boolify.call(r) }
|
2316
2370
|
|
2317
2371
|
if arg.is_a?(Array)
|
2318
2372
|
reply
|
@@ -2466,7 +2520,7 @@ class Redis
|
|
2466
2520
|
# @return [String, Array<[String, String]>] the next cursor and all found keys
|
2467
2521
|
def hscan(key, cursor, options={})
|
2468
2522
|
_scan(:hscan, cursor, [key], options) do |reply|
|
2469
|
-
[reply[0],
|
2523
|
+
[reply[0], reply[1].each_slice(2).to_a]
|
2470
2524
|
end
|
2471
2525
|
end
|
2472
2526
|
|
@@ -2505,7 +2559,7 @@ class Redis
|
|
2505
2559
|
# members and scores
|
2506
2560
|
def zscan(key, cursor, options={})
|
2507
2561
|
_scan(:zscan, cursor, [key], options) do |reply|
|
2508
|
-
[reply[0],
|
2562
|
+
[reply[0], FloatifyPairs.call(reply[1])]
|
2509
2563
|
end
|
2510
2564
|
end
|
2511
2565
|
|
@@ -2573,7 +2627,7 @@ class Redis
|
|
2573
2627
|
# @return [Boolean] true if at least 1 HyperLogLog internal register was altered. false otherwise.
|
2574
2628
|
def pfadd(key, member)
|
2575
2629
|
synchronize do |client|
|
2576
|
-
client.call([:pfadd, key, member], &
|
2630
|
+
client.call([:pfadd, key, member], &Boolify)
|
2577
2631
|
end
|
2578
2632
|
end
|
2579
2633
|
|
@@ -2598,7 +2652,7 @@ class Redis
|
|
2598
2652
|
# @return [Boolean]
|
2599
2653
|
def pfmerge(dest_key, *source_key)
|
2600
2654
|
synchronize do |client|
|
2601
|
-
client.call([:pfmerge, dest_key, *source_key], &
|
2655
|
+
client.call([:pfmerge, dest_key, *source_key], &BoolifySet)
|
2602
2656
|
end
|
2603
2657
|
end
|
2604
2658
|
|
@@ -2617,9 +2671,9 @@ class Redis
|
|
2617
2671
|
else
|
2618
2672
|
if reply.kind_of?(Array)
|
2619
2673
|
if reply[0].kind_of?(Array)
|
2620
|
-
reply.map(&
|
2674
|
+
reply.map(&Hashify)
|
2621
2675
|
else
|
2622
|
-
|
2676
|
+
Hashify.call(reply)
|
2623
2677
|
end
|
2624
2678
|
else
|
2625
2679
|
reply
|
@@ -2652,13 +2706,12 @@ private
|
|
2652
2706
|
# Commands returning 1 for true and 0 for false may be executed in a pipeline
|
2653
2707
|
# where the method call will return nil. Propagate the nil instead of falsely
|
2654
2708
|
# returning false.
|
2655
|
-
|
2709
|
+
Boolify =
|
2656
2710
|
lambda { |value|
|
2657
2711
|
value == 1 if value
|
2658
2712
|
}
|
2659
|
-
end
|
2660
2713
|
|
2661
|
-
|
2714
|
+
BoolifySet =
|
2662
2715
|
lambda { |value|
|
2663
2716
|
if value && "OK" == value
|
2664
2717
|
true
|
@@ -2666,9 +2719,8 @@ private
|
|
2666
2719
|
false
|
2667
2720
|
end
|
2668
2721
|
}
|
2669
|
-
end
|
2670
2722
|
|
2671
|
-
|
2723
|
+
Hashify =
|
2672
2724
|
lambda { |array|
|
2673
2725
|
hash = Hash.new
|
2674
2726
|
array.each_slice(2) do |field, value|
|
@@ -2676,46 +2728,37 @@ private
|
|
2676
2728
|
end
|
2677
2729
|
hash
|
2678
2730
|
}
|
2679
|
-
end
|
2680
2731
|
|
2681
|
-
|
2732
|
+
Floatify =
|
2682
2733
|
lambda { |str|
|
2683
|
-
|
2684
|
-
|
2685
|
-
|
2686
|
-
|
2687
|
-
|
2688
|
-
|
2734
|
+
if str
|
2735
|
+
if (inf = str.match(/^(-)?inf/i))
|
2736
|
+
(inf[1] ? -1.0 : 1.0) / 0.0
|
2737
|
+
else
|
2738
|
+
Float(str)
|
2739
|
+
end
|
2689
2740
|
end
|
2690
2741
|
}
|
2691
|
-
end
|
2692
2742
|
|
2693
|
-
|
2743
|
+
FloatifyPairs =
|
2694
2744
|
lambda { |array|
|
2695
|
-
|
2696
|
-
|
2697
|
-
|
2698
|
-
|
2745
|
+
if array
|
2746
|
+
array.each_slice(2).map do |member, score|
|
2747
|
+
[member, Floatify.call(score)]
|
2748
|
+
end
|
2699
2749
|
end
|
2700
2750
|
}
|
2701
|
-
end
|
2702
|
-
|
2703
|
-
def _pairify(array)
|
2704
|
-
array.each_slice(2).to_a
|
2705
|
-
end
|
2706
|
-
|
2707
|
-
def _identity
|
2708
|
-
lambda { |value|
|
2709
|
-
value
|
2710
|
-
}
|
2711
|
-
end
|
2712
2751
|
|
2713
|
-
def _subscription(method, channels, block)
|
2752
|
+
def _subscription(method, timeout, channels, block)
|
2714
2753
|
return @client.call([method] + channels) if subscribed?
|
2715
2754
|
|
2716
2755
|
begin
|
2717
2756
|
original, @client = @client, SubscribedClient.new(@client)
|
2718
|
-
|
2757
|
+
if timeout > 0
|
2758
|
+
@client.send(method, timeout, *channels, &block)
|
2759
|
+
else
|
2760
|
+
@client.send(method, *channels, &block)
|
2761
|
+
end
|
2719
2762
|
ensure
|
2720
2763
|
@client = original
|
2721
2764
|
end
|