redis 3.2.2 → 3.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +41 -11
- data/CHANGELOG.md +19 -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 +91 -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/internals_test.rb +20 -0
- 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/sentinel_command_test.rb +1 -1
- data/test/sentinel_test.rb +1 -1
- 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 +33 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4744291b8bc26230044fc12c456951a60c5802c7
|
4
|
+
data.tar.gz: 6eabe9bb60b74aa2408007a72f9a44e831b71a5e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fb460a3595ed430dbf4dab6f516dcbef029cf1c72350e4e50b7e425e8d94b8d47760d33f58db21bad95852ec97fa7fdba55cfb0858292c221c947516a291f97
|
7
|
+
data.tar.gz: 7cdf461c39d5eede9b295bf987391cd70461cd5adcee945ae243d509f67457ea14aa0ad08ca47efdab8bb8ca315d6bdff94460d6cecc6b981f459081cd93dfbd
|
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"
|
@@ -19,9 +21,12 @@ env:
|
|
19
21
|
- VERBOSE=true
|
20
22
|
- TIMEOUT=1
|
21
23
|
matrix:
|
22
|
-
- conn=ruby REDIS_BRANCH=
|
23
|
-
- conn=
|
24
|
-
- conn=
|
24
|
+
- conn=ruby REDIS_BRANCH=3.0
|
25
|
+
- conn=ruby REDIS_BRANCH=3.2
|
26
|
+
- conn=hiredis REDIS_BRANCH=3.0
|
27
|
+
- conn=hiredis REDIS_BRANCH=3.2
|
28
|
+
- conn=synchrony REDIS_BRANCH=3.0
|
29
|
+
- conn=synchrony REDIS_BRANCH=3.2
|
25
30
|
- conn=ruby REDIS_BRANCH=unstable
|
26
31
|
|
27
32
|
branches:
|
@@ -33,27 +38,52 @@ matrix:
|
|
33
38
|
# hiredis
|
34
39
|
- rvm: jruby-18mode
|
35
40
|
gemfile: .travis/Gemfile
|
36
|
-
env: conn=hiredis REDIS_BRANCH=
|
41
|
+
env: conn=hiredis REDIS_BRANCH=3.0
|
42
|
+
- rvm: jruby-18mode
|
43
|
+
gemfile: .travis/Gemfile
|
44
|
+
env: conn=hiredis REDIS_BRANCH=3.2
|
45
|
+
- rvm: jruby-19mode
|
46
|
+
gemfile: .travis/Gemfile
|
47
|
+
env: conn=hiredis REDIS_BRANCH=3.0
|
37
48
|
- rvm: jruby-19mode
|
38
49
|
gemfile: .travis/Gemfile
|
39
|
-
env: conn=hiredis REDIS_BRANCH=2
|
50
|
+
env: conn=hiredis REDIS_BRANCH=3.2
|
51
|
+
- rvm: jruby-9.0.5.0
|
52
|
+
gemfile: .travis/Gemfile
|
53
|
+
env: conn=hiredis REDIS_BRANCH=3.0
|
54
|
+
- rvm: jruby-9.0.5.0
|
55
|
+
gemfile: .travis/Gemfile
|
56
|
+
env: conn=hiredis REDIS_BRANCH=3.2
|
40
57
|
|
41
58
|
# synchrony
|
42
59
|
- rvm: 1.8.7
|
43
60
|
gemfile: .travis/Gemfile
|
44
|
-
env: conn=synchrony REDIS_BRANCH=
|
61
|
+
env: conn=synchrony REDIS_BRANCH=3.0
|
62
|
+
- rvm: 1.8.7
|
63
|
+
gemfile: .travis/Gemfile
|
64
|
+
env: conn=synchrony REDIS_BRANCH=3.2
|
65
|
+
- rvm: jruby-18mode
|
66
|
+
gemfile: .travis/Gemfile
|
67
|
+
env: conn=synchrony REDIS_BRANCH=3.0
|
45
68
|
- rvm: jruby-18mode
|
46
69
|
gemfile: .travis/Gemfile
|
47
|
-
env: conn=synchrony REDIS_BRANCH=2
|
70
|
+
env: conn=synchrony REDIS_BRANCH=3.2
|
48
71
|
- rvm: jruby-19mode
|
49
72
|
gemfile: .travis/Gemfile
|
50
|
-
env: conn=synchrony REDIS_BRANCH=
|
73
|
+
env: conn=synchrony REDIS_BRANCH=3.0
|
74
|
+
- rvm: jruby-19mode
|
75
|
+
gemfile: .travis/Gemfile
|
76
|
+
env: conn=synchrony REDIS_BRANCH=3.2
|
77
|
+
- rvm: jruby-9.0.5.0
|
78
|
+
gemfile: .travis/Gemfile
|
79
|
+
env: conn=synchrony REDIS_BRANCH=3.0
|
80
|
+
- rvm: jruby-9.0.5.0
|
81
|
+
gemfile: .travis/Gemfile
|
82
|
+
env: conn=synchrony REDIS_BRANCH=3.2
|
51
83
|
allow_failures:
|
52
84
|
- rvm: rbx-2
|
53
85
|
|
54
86
|
notifications:
|
55
87
|
irc:
|
56
88
|
- irc.freenode.net#redis-rb
|
57
|
-
email:
|
58
|
-
- damian.janowski@gmail.com
|
59
|
-
- pcnoordhuis@gmail.com
|
89
|
+
email: false
|
data/CHANGELOG.md
CHANGED
@@ -12,6 +12,25 @@
|
|
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.1
|
16
|
+
|
17
|
+
* Remove usage of Timeout::timeout, refactor into using low level non-blocking writes.
|
18
|
+
This fixes a memory leak due to Timeout creating threads on each invocation.
|
19
|
+
|
20
|
+
# 3.3.0
|
21
|
+
|
22
|
+
* Added support for SSL/TLS. Redis doesn't support SSL natively, so you still
|
23
|
+
need to run a terminating proxy on Redis' side. See #496.
|
24
|
+
|
25
|
+
* Added `read_timeout` and `write_timeout` options. See #437, #482.
|
26
|
+
|
27
|
+
* Added support for pub/sub with timeouts. See #329.
|
28
|
+
|
29
|
+
* Added `Redis#call`, `Redis#queue` and `Redis#commit` as a more minimal API to
|
30
|
+
the client.
|
31
|
+
|
32
|
+
* Deprecated `Redis#disconnect!` in favor of `Redis#close`.
|
33
|
+
|
15
34
|
# 3.2.2
|
16
35
|
|
17
36
|
* 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
|