redis 3.2.1 → 3.2.2
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 +5 -0
- data/CHANGELOG.md +11 -0
- data/README.md +18 -2
- data/examples/unicorn/unicorn.rb +1 -1
- data/lib/redis.rb +123 -27
- data/lib/redis/client.rb +2 -4
- data/lib/redis/hash_ring.rb +1 -0
- data/lib/redis/version.rb +1 -1
- data/redis.gemspec +1 -0
- data/test/connection_handling_test.rb +13 -0
- data/test/distributed_internals_test.rb +12 -3
- data/test/distributed_key_tags_test.rb +3 -3
- data/test/distributed_test.rb +1 -1
- data/test/lint/sorted_sets.rb +78 -0
- data/test/sentinel_command_test.rb +80 -0
- data/test/sentinel_test.rb +51 -37
- data/test/support/redis_mock.rb +27 -29
- data/test/url_param_test.rb +6 -0
- metadata +19 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 183e90b7d3961182b8b5b20b1295b6dd9d30df12
|
4
|
+
data.tar.gz: 60023071a61af0e34d85b0a999db0bc5877070ad
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a1d93f8ee26f3dfecb10d223d178e4f78aa399d3bc8a78a4db479f0e6d89bd77c97d9e113b0138d102fbecf3d0a4452ce5f0da9412e069726c3b1fd7bb7bf7a4
|
7
|
+
data.tar.gz: 1a2077544497d0f2a1cd9035677dc1d514a9395b070b10f380e8fcc35cbbbbbae898e1b4ad3e7ff44e2fb96930330cb66b021ccaa726451c2c15276ff26b0011
|
data/.travis.yml
CHANGED
@@ -3,9 +3,12 @@ language: ruby
|
|
3
3
|
rvm:
|
4
4
|
- 1.8.7
|
5
5
|
- 1.9.3
|
6
|
+
- 2.0
|
6
7
|
- 2.1
|
8
|
+
- 2.2
|
7
9
|
- jruby-18mode
|
8
10
|
- jruby-19mode
|
11
|
+
- rbx-2
|
9
12
|
|
10
13
|
gemfile: ".travis/Gemfile"
|
11
14
|
|
@@ -45,6 +48,8 @@ matrix:
|
|
45
48
|
- rvm: jruby-19mode
|
46
49
|
gemfile: .travis/Gemfile
|
47
50
|
env: conn=synchrony REDIS_BRANCH=2.8
|
51
|
+
allow_failures:
|
52
|
+
- rvm: rbx-2
|
48
53
|
|
49
54
|
notifications:
|
50
55
|
irc:
|
data/CHANGELOG.md
CHANGED
@@ -12,6 +12,17 @@
|
|
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.2.2
|
16
|
+
|
17
|
+
* Added support for `ZADD` options `NX`, `XX`, `CH`, `INCR`. See #547.
|
18
|
+
|
19
|
+
* Added support for sentinel commands. See #556.
|
20
|
+
|
21
|
+
* New `:id` option allows you to identify the client against Redis. See #510.
|
22
|
+
|
23
|
+
* `Redis::Distributed` will raise when adding two nodes with the same ID.
|
24
|
+
See #354.
|
25
|
+
|
15
26
|
# 3.2.1
|
16
27
|
|
17
28
|
* Added support for `PUBSUB` command.
|
data/README.md
CHANGED
@@ -23,6 +23,20 @@ most important changes, as well as a full list of changes.
|
|
23
23
|
|
24
24
|
## Getting started
|
25
25
|
|
26
|
+
To install **redis-rb**, run the following command:
|
27
|
+
|
28
|
+
```
|
29
|
+
gem install redis
|
30
|
+
```
|
31
|
+
|
32
|
+
Or if you are using **bundler**, add
|
33
|
+
|
34
|
+
```
|
35
|
+
gem 'redis', '~>3.2'
|
36
|
+
```
|
37
|
+
|
38
|
+
to your `Gemfile`, and run `bundle install`
|
39
|
+
|
26
40
|
As of version 2.0 this client only targets Redis version 2.0 and higher.
|
27
41
|
You can use an older version of this client if you need to interface
|
28
42
|
with a Redis instance older than 2.0, but this is no longer supported.
|
@@ -43,12 +57,14 @@ server or a different port, try:
|
|
43
57
|
redis = Redis.new(:host => "10.0.1.1", :port => 6380, :db => 15)
|
44
58
|
```
|
45
59
|
|
46
|
-
You can also specify connection options as
|
60
|
+
You can also specify connection options as a [`redis://` URL][redis-url]:
|
47
61
|
|
48
62
|
```ruby
|
49
63
|
redis = Redis.new(:url => "redis://:p4ssw0rd@10.0.1.1:6380/15")
|
50
64
|
```
|
51
65
|
|
66
|
+
[redis-url]: http://www.iana.org/assignments/uri-schemes/prov/redis
|
67
|
+
|
52
68
|
By default, the client will try to read the `REDIS_URL` environment variable
|
53
69
|
and use that as URL to connect to. The above statement is therefore equivalent
|
54
70
|
to setting this environment variable and calling `Redis.new` without arguments.
|
@@ -298,7 +314,7 @@ all contributors)
|
|
298
314
|
* Matthew Clark
|
299
315
|
* Brian McKinney
|
300
316
|
* Luca Guidi
|
301
|
-
* Salvatore
|
317
|
+
* Salvatore Sanfilippo
|
302
318
|
* Chris Wanstrath
|
303
319
|
* Damian Janowski
|
304
320
|
* Michel Martens
|
data/examples/unicorn/unicorn.rb
CHANGED
data/lib/redis.rb
CHANGED
@@ -26,6 +26,26 @@ class Redis
|
|
26
26
|
|
27
27
|
include MonitorMixin
|
28
28
|
|
29
|
+
# Create a new client instance
|
30
|
+
#
|
31
|
+
# @param [Hash] options
|
32
|
+
# @option options [String] :url (value of the environment variable REDIS_URL) a Redis URL, for a TCP connection: `redis://:[password]@[hostname]:[port]/[db]` (password, port and database are optional), for a unix socket connection: `unix://[path to Redis socket]`. This overrides all other options.
|
33
|
+
# @option options [String] :host ("127.0.0.1") server hostname
|
34
|
+
# @option options [Fixnum] :port (6379) server port
|
35
|
+
# @option options [String] :path path to server socket (overrides host and port)
|
36
|
+
# @option options [Float] :timeout (5.0) timeout in seconds
|
37
|
+
# @option options [Float] :connect_timeout (same as timeout) timeout for initial connect in seconds
|
38
|
+
# @option options [String] :password Password to authenticate against server
|
39
|
+
# @option options [Fixnum] :db (0) Database to select after initial connect
|
40
|
+
# @option options [Symbol] :driver Driver to use, currently supported: `:ruby`, `:hiredis`, `:synchrony`
|
41
|
+
# @option options [String] :id ID for the client connection, assigns name to current connection by sending `CLIENT SETNAME`
|
42
|
+
# @option options [Hash, Fixnum] :tcp_keepalive Keepalive values, if Fixnum `intvl` and `probe` are calculated based on the value, if Hash `time`, `intvl` and `probes` can be specified as a Fixnum
|
43
|
+
# @option options [Fixnum] :reconnect_attempts Number of attempts trying to connect
|
44
|
+
# @option options [Boolean] :inherit_socket (false) Whether to use socket in forked process or not
|
45
|
+
# @option options [Array] :sentinels List of sentinels to contact
|
46
|
+
# @option options [Symbol] :role (:master) Role to fetch via Sentinel, either `:master` or `:slave`
|
47
|
+
#
|
48
|
+
# @return [Redis] a new client instance
|
29
49
|
def initialize(options = {})
|
30
50
|
@options = options.dup
|
31
51
|
@original_client = @client = Client.new(options)
|
@@ -329,8 +349,15 @@ class Redis
|
|
329
349
|
# Get the time to live (in seconds) for a key.
|
330
350
|
#
|
331
351
|
# @param [String] key
|
332
|
-
# @return [Fixnum] remaining time to live in seconds
|
333
|
-
#
|
352
|
+
# @return [Fixnum] remaining time to live in seconds.
|
353
|
+
#
|
354
|
+
# In Redis 2.6 or older the command returns -1 if the key does not exist or if
|
355
|
+
# the key exist but has no associated expire.
|
356
|
+
#
|
357
|
+
# Starting with Redis 2.8 the return value in case of error changed:
|
358
|
+
#
|
359
|
+
# - The command returns -2 if the key does not exist.
|
360
|
+
# - The command returns -1 if the key exists but has no associated expire.
|
334
361
|
def ttl(key)
|
335
362
|
synchronize do |client|
|
336
363
|
client.call([:ttl, key])
|
@@ -362,8 +389,14 @@ class Redis
|
|
362
389
|
# Get the time to live (in milliseconds) for a key.
|
363
390
|
#
|
364
391
|
# @param [String] key
|
365
|
-
# @return [Fixnum] remaining time to live in milliseconds
|
366
|
-
#
|
392
|
+
# @return [Fixnum] remaining time to live in milliseconds
|
393
|
+
# In Redis 2.6 or older the command returns -1 if the key does not exist or if
|
394
|
+
# the key exist but has no associated expire.
|
395
|
+
#
|
396
|
+
# Starting with Redis 2.8 the return value in case of error changed:
|
397
|
+
#
|
398
|
+
# - The command returns -2 if the key does not exist.
|
399
|
+
# - The command returns -1 if the key exists but has no associated expire.
|
367
400
|
def pttl(key)
|
368
401
|
synchronize do |client|
|
369
402
|
client.call([:pttl, key])
|
@@ -385,7 +418,7 @@ class Redis
|
|
385
418
|
# @param [String] key
|
386
419
|
# @param [String] ttl
|
387
420
|
# @param [String] serialized_value
|
388
|
-
# @return `"OK"`
|
421
|
+
# @return [String] `"OK"`
|
389
422
|
def restore(key, ttl, serialized_value)
|
390
423
|
synchronize do |client|
|
391
424
|
client.call([:restore, key, ttl, serialized_value])
|
@@ -690,7 +723,7 @@ class Redis
|
|
690
723
|
# @param [String] key
|
691
724
|
# @param [Fixnum] ttl
|
692
725
|
# @param [String] value
|
693
|
-
# @return `"OK"`
|
726
|
+
# @return [String] `"OK"`
|
694
727
|
def setex(key, ttl, value)
|
695
728
|
synchronize do |client|
|
696
729
|
client.call([:setex, key, ttl, value.to_s])
|
@@ -702,7 +735,7 @@ class Redis
|
|
702
735
|
# @param [String] key
|
703
736
|
# @param [Fixnum] ttl
|
704
737
|
# @param [String] value
|
705
|
-
# @return `"OK"`
|
738
|
+
# @return [String] `"OK"`
|
706
739
|
def psetex(key, ttl, value)
|
707
740
|
synchronize do |client|
|
708
741
|
client.call([:psetex, key, ttl, value.to_s])
|
@@ -727,7 +760,7 @@ class Redis
|
|
727
760
|
# # => "OK"
|
728
761
|
#
|
729
762
|
# @param [Array<String>] args array of keys and values
|
730
|
-
# @return `"OK"`
|
763
|
+
# @return [String] `"OK"`
|
731
764
|
#
|
732
765
|
# @see #mapped_mset
|
733
766
|
def mset(*args)
|
@@ -743,7 +776,7 @@ class Redis
|
|
743
776
|
# # => "OK"
|
744
777
|
#
|
745
778
|
# @param [Hash] hash keys mapping to values
|
746
|
-
# @return `"OK"`
|
779
|
+
# @return [String] `"OK"`
|
747
780
|
#
|
748
781
|
# @see #mset
|
749
782
|
def mapped_mset(hash)
|
@@ -968,7 +1001,7 @@ class Redis
|
|
968
1001
|
# Prepend one or more values to a list, creating the list if it doesn't exist
|
969
1002
|
#
|
970
1003
|
# @param [String] key
|
971
|
-
# @param [String, Array] string value, or array of string values to push
|
1004
|
+
# @param [String, Array] value string value, or array of string values to push
|
972
1005
|
# @return [Fixnum] the length of the list after the push operation
|
973
1006
|
def lpush(key, value)
|
974
1007
|
synchronize do |client|
|
@@ -1410,20 +1443,50 @@ class Redis
|
|
1410
1443
|
# @param [[Float, String], Array<[Float, String]>] args
|
1411
1444
|
# - a single `[score, member]` pair
|
1412
1445
|
# - an array of `[score, member]` pairs
|
1413
|
-
#
|
1414
|
-
#
|
1446
|
+
# @param [Hash] options
|
1447
|
+
# - `:xx => true`: Only update elements that already exist (never
|
1448
|
+
# add elements)
|
1449
|
+
# - `:nx => true`: Don't update already existing elements (always
|
1450
|
+
# add new elements)
|
1451
|
+
# - `:ch => true`: Modify the return value from the number of new
|
1452
|
+
# elements added, to the total number of elements changed (CH is an
|
1453
|
+
# abbreviation of changed); changed elements are new elements added
|
1454
|
+
# and elements already existing for which the score was updated
|
1455
|
+
# - `:incr => true`: When this option is specified ZADD acts like
|
1456
|
+
# ZINCRBY; only one score-element pair can be specified in this mode
|
1457
|
+
#
|
1458
|
+
# @return [Boolean, Fixnum, Float]
|
1415
1459
|
# - `Boolean` when a single pair is specified, holding whether or not it was
|
1416
|
-
# **added** to the sorted set
|
1460
|
+
# **added** to the sorted set.
|
1417
1461
|
# - `Fixnum` when an array of pairs is specified, holding the number of
|
1418
|
-
# pairs that were **added** to the sorted set
|
1419
|
-
|
1462
|
+
# pairs that were **added** to the sorted set.
|
1463
|
+
# - `Float` when option :incr is specified, holding the score of the member
|
1464
|
+
# after incrementing it.
|
1465
|
+
def zadd(key, *args) #, options
|
1466
|
+
zadd_options = []
|
1467
|
+
if args.last.is_a?(Hash)
|
1468
|
+
options = args.pop
|
1469
|
+
|
1470
|
+
nx = options[:nx]
|
1471
|
+
zadd_options << "NX" if nx
|
1472
|
+
|
1473
|
+
xx = options[:xx]
|
1474
|
+
zadd_options << "XX" if xx
|
1475
|
+
|
1476
|
+
ch = options[:ch]
|
1477
|
+
zadd_options << "CH" if ch
|
1478
|
+
|
1479
|
+
incr = options[:incr]
|
1480
|
+
zadd_options << "INCR" if incr
|
1481
|
+
end
|
1482
|
+
|
1420
1483
|
synchronize do |client|
|
1421
1484
|
if args.size == 1 && args[0].is_a?(Array)
|
1422
|
-
# Variadic: return integer
|
1423
|
-
client.call([:zadd, key] + args[0])
|
1485
|
+
# Variadic: return float if INCR, integer if !INCR
|
1486
|
+
client.call([:zadd, key] + zadd_options + args[0], &(incr ? _floatify : _identity))
|
1424
1487
|
elsif args.size == 2
|
1425
|
-
# Single pair: return boolean
|
1426
|
-
client.call([:zadd, key
|
1488
|
+
# Single pair: return float if INCR, boolean if !INCR
|
1489
|
+
client.call([:zadd, key] + zadd_options + args, &(incr ? _floatify : _boolify))
|
1427
1490
|
else
|
1428
1491
|
raise ArgumentError, "wrong number of arguments"
|
1429
1492
|
end
|
@@ -1867,7 +1930,7 @@ class Redis
|
|
1867
1930
|
#
|
1868
1931
|
# @param [String] key
|
1869
1932
|
# @param [Array<String>] attrs array of fields and values
|
1870
|
-
# @return `"OK"`
|
1933
|
+
# @return [String] `"OK"`
|
1871
1934
|
#
|
1872
1935
|
# @see #mapped_hmset
|
1873
1936
|
def hmset(key, *attrs)
|
@@ -1883,8 +1946,8 @@ class Redis
|
|
1883
1946
|
# # => "OK"
|
1884
1947
|
#
|
1885
1948
|
# @param [String] key
|
1886
|
-
# @param [Hash] a non-empty hash with fields mapping to values
|
1887
|
-
# @return `"OK"`
|
1949
|
+
# @param [Hash] hash a non-empty hash with fields mapping to values
|
1950
|
+
# @return [String] `"OK"`
|
1888
1951
|
#
|
1889
1952
|
# @see #hmset
|
1890
1953
|
def mapped_hmset(key, hash)
|
@@ -2207,7 +2270,7 @@ class Redis
|
|
2207
2270
|
#
|
2208
2271
|
# Only call this method when `#multi` was called **without** a block.
|
2209
2272
|
#
|
2210
|
-
# @return `"OK"`
|
2273
|
+
# @return [String] `"OK"`
|
2211
2274
|
#
|
2212
2275
|
# @see #multi
|
2213
2276
|
# @see #exec
|
@@ -2355,7 +2418,7 @@ class Redis
|
|
2355
2418
|
# redis.scan(4, :match => "key:1?")
|
2356
2419
|
# # => ["92", ["key:13", "key:18"]]
|
2357
2420
|
#
|
2358
|
-
# @param [String, Integer] cursor
|
2421
|
+
# @param [String, Integer] cursor the cursor of the iteration
|
2359
2422
|
# @param [Hash] options
|
2360
2423
|
# - `:match => String`: only return keys matching the pattern
|
2361
2424
|
# - `:count => Integer`: return count keys at most per iteration
|
@@ -2395,7 +2458,7 @@ class Redis
|
|
2395
2458
|
# @example Retrieve the first batch of key/value pairs in a hash
|
2396
2459
|
# redis.hscan("hash", 0)
|
2397
2460
|
#
|
2398
|
-
# @param [String, Integer] cursor
|
2461
|
+
# @param [String, Integer] cursor the cursor of the iteration
|
2399
2462
|
# @param [Hash] options
|
2400
2463
|
# - `:match => String`: only return keys matching the pattern
|
2401
2464
|
# - `:count => Integer`: return count keys at most per iteration
|
@@ -2433,7 +2496,7 @@ class Redis
|
|
2433
2496
|
# @example Retrieve the first batch of key/value pairs in a hash
|
2434
2497
|
# redis.zscan("zset", 0)
|
2435
2498
|
#
|
2436
|
-
# @param [String, Integer] cursor
|
2499
|
+
# @param [String, Integer] cursor the cursor of the iteration
|
2437
2500
|
# @param [Hash] options
|
2438
2501
|
# - `:match => String`: only return keys matching the pattern
|
2439
2502
|
# - `:count => Integer`: return count keys at most per iteration
|
@@ -2472,7 +2535,7 @@ class Redis
|
|
2472
2535
|
# @example Retrieve the first batch of keys in a set
|
2473
2536
|
# redis.sscan("set", 0)
|
2474
2537
|
#
|
2475
|
-
# @param [String, Integer] cursor
|
2538
|
+
# @param [String, Integer] cursor the cursor of the iteration
|
2476
2539
|
# @param [Hash] options
|
2477
2540
|
# - `:match => String`: only return keys matching the pattern
|
2478
2541
|
# - `:count => Integer`: return count keys at most per iteration
|
@@ -2539,6 +2602,33 @@ class Redis
|
|
2539
2602
|
end
|
2540
2603
|
end
|
2541
2604
|
|
2605
|
+
# Interact with the sentinel command (masters, master, slaves, failover)
|
2606
|
+
#
|
2607
|
+
# @param [String] subcommand e.g. `masters`, `master`, `slaves`
|
2608
|
+
# @param [Array<String>] args depends on subcommand
|
2609
|
+
# @return [Array<String>, Hash<String, String>, String] depends on subcommand
|
2610
|
+
def sentinel(subcommand, *args)
|
2611
|
+
subcommand = subcommand.to_s.downcase
|
2612
|
+
synchronize do |client|
|
2613
|
+
client.call([:sentinel, subcommand] + args) do |reply|
|
2614
|
+
case subcommand
|
2615
|
+
when "get-master-addr-by-name"
|
2616
|
+
reply
|
2617
|
+
else
|
2618
|
+
if reply.kind_of?(Array)
|
2619
|
+
if reply[0].kind_of?(Array)
|
2620
|
+
reply.map(&_hashify)
|
2621
|
+
else
|
2622
|
+
_hashify.call(reply)
|
2623
|
+
end
|
2624
|
+
else
|
2625
|
+
reply
|
2626
|
+
end
|
2627
|
+
end
|
2628
|
+
end
|
2629
|
+
end
|
2630
|
+
end
|
2631
|
+
|
2542
2632
|
def id
|
2543
2633
|
@original_client.id
|
2544
2634
|
end
|
@@ -2614,6 +2704,12 @@ private
|
|
2614
2704
|
array.each_slice(2).to_a
|
2615
2705
|
end
|
2616
2706
|
|
2707
|
+
def _identity
|
2708
|
+
lambda { |value|
|
2709
|
+
value
|
2710
|
+
}
|
2711
|
+
end
|
2712
|
+
|
2617
2713
|
def _subscription(method, channels, block)
|
2618
2714
|
return @client.call([method] + channels) if subscribed?
|
2619
2715
|
|
data/lib/redis/client.rb
CHANGED
@@ -94,6 +94,7 @@ class Redis
|
|
94
94
|
establish_connection
|
95
95
|
call [:auth, password] if password
|
96
96
|
call [:select, db] if db != 0
|
97
|
+
call [:client, :setname, @options[:id]] if @options[:id]
|
97
98
|
@connector.check(self)
|
98
99
|
end
|
99
100
|
|
@@ -392,11 +393,8 @@ class Redis
|
|
392
393
|
if uri.scheme == "unix"
|
393
394
|
defaults[:path] = uri.path
|
394
395
|
elsif uri.scheme == "redis"
|
395
|
-
# Require the URL to have at least a host
|
396
|
-
raise ArgumentError, "invalid url: #{uri}" unless uri.host
|
397
|
-
|
398
396
|
defaults[:scheme] = uri.scheme
|
399
|
-
defaults[:host] = uri.host
|
397
|
+
defaults[:host] = uri.host if uri.host
|
400
398
|
defaults[:port] = uri.port if uri.port
|
401
399
|
defaults[:password] = CGI.unescape(uri.password) if uri.password
|
402
400
|
defaults[:db] = uri.path[1..-1].to_i if uri.path
|
data/lib/redis/hash_ring.rb
CHANGED
data/lib/redis/version.rb
CHANGED
data/redis.gemspec
CHANGED
@@ -17,6 +17,19 @@ class TestConnectionHandling < Test::Unit::TestCase
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
def test_id
|
21
|
+
commands = {
|
22
|
+
:client => lambda { |cmd, name| $name = [cmd, name]; "+OK" },
|
23
|
+
:ping => lambda { "+PONG" },
|
24
|
+
}
|
25
|
+
|
26
|
+
redis_mock(commands, :id => "client-name") do |redis|
|
27
|
+
assert_equal "PONG", redis.ping
|
28
|
+
end
|
29
|
+
|
30
|
+
assert_equal ["setname","client-name"], $name
|
31
|
+
end
|
32
|
+
|
20
33
|
def test_ping
|
21
34
|
assert_equal "PONG", r.ping
|
22
35
|
end
|
@@ -7,16 +7,16 @@ class TestDistributedInternals < Test::Unit::TestCase
|
|
7
7
|
include Helper::Distributed
|
8
8
|
|
9
9
|
def test_provides_a_meaningful_inspect
|
10
|
-
nodes = ["redis://
|
10
|
+
nodes = ["redis://localhost:#{PORT}/15", *NODES]
|
11
11
|
redis = Redis::Distributed.new nodes
|
12
12
|
|
13
13
|
assert_equal "#<Redis client v#{Redis::VERSION} for #{redis.nodes.map(&:id).join(', ')}>", redis.inspect
|
14
14
|
end
|
15
15
|
|
16
16
|
def test_default_as_urls
|
17
|
-
nodes = ["redis://
|
17
|
+
nodes = ["redis://localhost:#{PORT}/15", *NODES]
|
18
18
|
redis = Redis::Distributed.new nodes
|
19
|
-
assert_equal ["redis://
|
19
|
+
assert_equal ["redis://localhost:#{PORT}/15", *NODES], redis.nodes.map { |node| node.client.id}
|
20
20
|
end
|
21
21
|
|
22
22
|
def test_default_as_config_hashes
|
@@ -67,4 +67,13 @@ class TestDistributedInternals < Test::Unit::TestCase
|
|
67
67
|
|
68
68
|
assert_equal [], r2.sinter("baz:foo", "baz:bar")
|
69
69
|
end
|
70
|
+
|
71
|
+
def test_colliding_node_ids
|
72
|
+
nodes = ["redis://localhost:#{PORT}/15", "redis://localhost:#{PORT}/15", *NODES]
|
73
|
+
|
74
|
+
assert_raise(RuntimeError) do
|
75
|
+
redis = Redis::Distributed.new nodes
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
70
79
|
end
|
@@ -8,9 +8,9 @@ class TestDistributedKeyTags < Test::Unit::TestCase
|
|
8
8
|
include Helper::Distributed
|
9
9
|
|
10
10
|
def test_hashes_consistently
|
11
|
-
r1 = Redis::Distributed.new ["redis://
|
12
|
-
r2 = Redis::Distributed.new ["redis://
|
13
|
-
r3 = Redis::Distributed.new ["redis://
|
11
|
+
r1 = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
|
12
|
+
r2 = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
|
13
|
+
r3 = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
|
14
14
|
|
15
15
|
assert_equal r1.node_for("foo").id, r2.node_for("foo").id
|
16
16
|
assert_equal r1.node_for("foo").id, r3.node_for("foo").id
|
data/test/distributed_test.rb
CHANGED
@@ -7,7 +7,7 @@ class TestDistributed < Test::Unit::TestCase
|
|
7
7
|
include Helper::Distributed
|
8
8
|
|
9
9
|
def test_handle_multiple_servers
|
10
|
-
@r = Redis::Distributed.new ["redis://
|
10
|
+
@r = Redis::Distributed.new ["redis://localhost:#{PORT}/15", *NODES]
|
11
11
|
|
12
12
|
100.times do |idx|
|
13
13
|
@r.set(idx.to_s, "foo#{idx}")
|
data/test/lint/sorted_sets.rb
CHANGED
@@ -9,6 +9,43 @@ module Lint
|
|
9
9
|
assert_equal true, r.zadd("foo", 1, "s1")
|
10
10
|
assert_equal false, r.zadd("foo", 1, "s1")
|
11
11
|
assert_equal 1, r.zcard("foo")
|
12
|
+
r.del "foo"
|
13
|
+
|
14
|
+
target_version "3.0.2" do
|
15
|
+
# XX option
|
16
|
+
assert_equal 0, r.zcard("foo")
|
17
|
+
assert_equal false, r.zadd("foo", 1, "s1", :xx => true)
|
18
|
+
r.zadd("foo", 1, "s1")
|
19
|
+
assert_equal false, r.zadd("foo", 2, "s1", :xx => true)
|
20
|
+
assert_equal 2, r.zscore("foo", "s1")
|
21
|
+
r.del "foo"
|
22
|
+
|
23
|
+
# NX option
|
24
|
+
assert_equal 0, r.zcard("foo")
|
25
|
+
assert_equal true, r.zadd("foo", 1, "s1", :nx => true)
|
26
|
+
assert_equal false, r.zadd("foo", 2, "s1", :nx => true)
|
27
|
+
assert_equal 1, r.zscore("foo", "s1")
|
28
|
+
assert_equal 1, r.zcard("foo")
|
29
|
+
r.del "foo"
|
30
|
+
|
31
|
+
# CH option
|
32
|
+
assert_equal 0, r.zcard("foo")
|
33
|
+
assert_equal true, r.zadd("foo", 1, "s1", :ch => true)
|
34
|
+
assert_equal false, r.zadd("foo", 1, "s1", :ch => true)
|
35
|
+
assert_equal true, r.zadd("foo", 2, "s1", :ch => true)
|
36
|
+
assert_equal 1, r.zcard("foo")
|
37
|
+
r.del "foo"
|
38
|
+
|
39
|
+
# INCR option
|
40
|
+
assert_equal 1.0, r.zadd("foo", 1, "s1", :incr => true)
|
41
|
+
assert_equal 11.0, r.zadd("foo", 10, "s1", :incr => true)
|
42
|
+
assert_equal -Infinity, r.zadd("bar", "-inf", "s1", :incr => true)
|
43
|
+
assert_equal +Infinity, r.zadd("bar", "+inf", "s2", :incr => true)
|
44
|
+
r.del "foo", "bar"
|
45
|
+
|
46
|
+
# Incompatible options combination
|
47
|
+
assert_raise(Redis::CommandError) { r.zadd("foo", 1, "s1", :xx => true, :nx => true) }
|
48
|
+
end
|
12
49
|
end
|
13
50
|
|
14
51
|
def test_variadic_zadd
|
@@ -31,6 +68,47 @@ module Lint
|
|
31
68
|
assert_raise(Redis::CommandError) { r.zadd("foo", ["bar"]) }
|
32
69
|
assert_raise(Redis::CommandError) { r.zadd("foo", ["bar", "qux", "zap"]) }
|
33
70
|
end
|
71
|
+
|
72
|
+
target_version "3.0.2" do
|
73
|
+
# XX option
|
74
|
+
assert_equal 0, r.zcard("foo")
|
75
|
+
assert_equal 0, r.zadd("foo", [1, "s1", 2, "s2"], :xx => true)
|
76
|
+
r.zadd("foo", [1, "s1", 2, "s2"])
|
77
|
+
assert_equal 0, r.zadd("foo", [2, "s1", 3, "s2", 4, "s3"], :xx => true)
|
78
|
+
assert_equal 2, r.zscore("foo", "s1")
|
79
|
+
assert_equal 3, r.zscore("foo", "s2")
|
80
|
+
assert_equal nil, r.zscore("foo", "s3")
|
81
|
+
assert_equal 2, r.zcard("foo")
|
82
|
+
r.del "foo"
|
83
|
+
|
84
|
+
# NX option
|
85
|
+
assert_equal 0, r.zcard("foo")
|
86
|
+
assert_equal 2, r.zadd("foo", [1, "s1", 2, "s2"], :nx => true)
|
87
|
+
assert_equal 1, r.zadd("foo", [2, "s1", 3, "s2", 4, "s3"], :nx => true)
|
88
|
+
assert_equal 1, r.zscore("foo", "s1")
|
89
|
+
assert_equal 2, r.zscore("foo", "s2")
|
90
|
+
assert_equal 4, r.zscore("foo", "s3")
|
91
|
+
assert_equal 3, r.zcard("foo")
|
92
|
+
r.del "foo"
|
93
|
+
|
94
|
+
# CH option
|
95
|
+
assert_equal 0, r.zcard("foo")
|
96
|
+
assert_equal 2, r.zadd("foo", [1, "s1", 2, "s2"], :ch => true)
|
97
|
+
assert_equal 2, r.zadd("foo", [1, "s1", 3, "s2", 4, "s3"], :ch => true)
|
98
|
+
assert_equal 3, r.zcard("foo")
|
99
|
+
r.del "foo"
|
100
|
+
|
101
|
+
# INCR option
|
102
|
+
assert_equal 1.0, r.zadd("foo", [1, "s1"], :incr => true)
|
103
|
+
assert_equal 11.0, r.zadd("foo", [10, "s1"], :incr => true)
|
104
|
+
assert_equal -Infinity, r.zadd("bar", ["-inf", "s1"], :incr => true)
|
105
|
+
assert_equal +Infinity, r.zadd("bar", ["+inf", "s2"], :incr => true)
|
106
|
+
assert_raise(Redis::CommandError) { r.zadd("foo", [1, "s1", 2, "s2"], :incr => true) }
|
107
|
+
r.del "foo", "bar"
|
108
|
+
|
109
|
+
# Incompatible options combination
|
110
|
+
assert_raise(Redis::CommandError) { r.zadd("foo", [1, "s1"], :xx => true, :nx => true) }
|
111
|
+
end
|
34
112
|
end
|
35
113
|
|
36
114
|
def test_zrem
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
require File.expand_path("helper", File.dirname(__FILE__))
|
4
|
+
|
5
|
+
class SentinalCommandsTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
include Helper::Client
|
8
|
+
|
9
|
+
def test_sentinel_command_master
|
10
|
+
|
11
|
+
handler = lambda do |id|
|
12
|
+
{
|
13
|
+
:sentinel => lambda do |command, *args|
|
14
|
+
["name", "master1", "ip", "127.0.0.1"]
|
15
|
+
end
|
16
|
+
}
|
17
|
+
end
|
18
|
+
|
19
|
+
RedisMock.start(handler.call(:s1)) do |port|
|
20
|
+
redis = Redis.new(:host => "127.0.0.1", :port => port)
|
21
|
+
|
22
|
+
result = redis.sentinel('master', 'master1')
|
23
|
+
assert_equal result, { "name" => "master1", "ip" => "127.0.0.1" }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_sentinel_command_masters
|
28
|
+
|
29
|
+
handler = lambda do |id|
|
30
|
+
{
|
31
|
+
:sentinel => lambda do |command, *args|
|
32
|
+
[%w[name master1 ip 127.0.0.1 port 6381], %w[name master1 ip 127.0.0.1 port 6382]]
|
33
|
+
end
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
RedisMock.start(handler.call(:s1)) do |port|
|
38
|
+
redis = Redis.new(:host => "127.0.0.1", :port => port)
|
39
|
+
|
40
|
+
result = redis.sentinel('masters')
|
41
|
+
assert_equal result[0], { "name" => "master1", "ip" => "127.0.0.1", "port" => "6381" }
|
42
|
+
assert_equal result[1], { "name" => "master1", "ip" => "127.0.0.1", "port" => "6382" }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_sentinel_command_get_master_by_name
|
47
|
+
|
48
|
+
handler = lambda do |id|
|
49
|
+
{
|
50
|
+
:sentinel => lambda do |command, *args|
|
51
|
+
["127.0.0.1", "6381"]
|
52
|
+
end
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
RedisMock.start(handler.call(:s1)) do |port|
|
57
|
+
redis = Redis.new(:host => "127.0.0.1", :port => port)
|
58
|
+
|
59
|
+
result = redis.sentinel('get-master-addr-by-name', 'master1')
|
60
|
+
assert_equal result, ["127.0.0.1", "6381"]
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_sentinel_command_ckquorum
|
65
|
+
handler = lambda do |id|
|
66
|
+
{
|
67
|
+
:sentinel => lambda do |command, *args|
|
68
|
+
"+OK 2 usable Sentinels. Quorum and failover authorization can be reached"
|
69
|
+
end
|
70
|
+
}
|
71
|
+
end
|
72
|
+
|
73
|
+
RedisMock.start(handler.call(:s1)) do |port|
|
74
|
+
redis = Redis.new(:host => "127.0.0.1", :port => port)
|
75
|
+
|
76
|
+
result = redis.sentinel('ckquorum', 'master1')
|
77
|
+
assert_equal result, "OK 2 usable Sentinels. Quorum and failover authorization can be reached"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
data/test/sentinel_test.rb
CHANGED
@@ -24,8 +24,10 @@ class SentinalTest < Test::Unit::TestCase
|
|
24
24
|
}
|
25
25
|
end
|
26
26
|
|
27
|
-
RedisMock.start(handler.call(:s1)
|
28
|
-
RedisMock.start(handler.call(:s2)
|
27
|
+
RedisMock.start(handler.call(:s1)) do |s1_port|
|
28
|
+
RedisMock.start(handler.call(:s2)) do |s2_port|
|
29
|
+
sentinels[0][:port] = s1_port
|
30
|
+
sentinels[1][:port] = s2_port
|
29
31
|
redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master)
|
30
32
|
|
31
33
|
assert redis.ping
|
@@ -59,8 +61,10 @@ class SentinalTest < Test::Unit::TestCase
|
|
59
61
|
end
|
60
62
|
}
|
61
63
|
|
62
|
-
RedisMock.start(s1
|
63
|
-
RedisMock.start(s2
|
64
|
+
RedisMock.start(s1) do |s1_port|
|
65
|
+
RedisMock.start(s2) do |s2_port|
|
66
|
+
sentinels[0][:port] = s1_port
|
67
|
+
sentinels[1][:port] = s2_port
|
64
68
|
redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master)
|
65
69
|
|
66
70
|
assert redis.ping
|
@@ -94,8 +98,10 @@ class SentinalTest < Test::Unit::TestCase
|
|
94
98
|
end
|
95
99
|
}
|
96
100
|
|
97
|
-
RedisMock.start(s1
|
98
|
-
RedisMock.start(s2
|
101
|
+
RedisMock.start(s1) do |s1_port|
|
102
|
+
RedisMock.start(s2) do |s2_port|
|
103
|
+
sentinels[0][:port] = s1_port
|
104
|
+
sentinels[1][:port] = s2_port
|
99
105
|
redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master)
|
100
106
|
|
101
107
|
assert redis.ping
|
@@ -118,20 +124,22 @@ class SentinalTest < Test::Unit::TestCase
|
|
118
124
|
:m1 => []
|
119
125
|
}
|
120
126
|
|
121
|
-
sentinel =
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
127
|
+
sentinel = lambda do |port|
|
128
|
+
{
|
129
|
+
:auth => lambda do |pass|
|
130
|
+
commands[:s1] << ["auth", pass]
|
131
|
+
"-ERR unknown command 'auth'"
|
132
|
+
end,
|
133
|
+
:select => lambda do |db|
|
134
|
+
commands[:s1] << ["select", db]
|
135
|
+
"-ERR unknown command 'select'"
|
136
|
+
end,
|
137
|
+
:sentinel => lambda do |command, *args|
|
138
|
+
commands[:s1] << [command, *args]
|
139
|
+
["127.0.0.1", port.to_s]
|
140
|
+
end
|
141
|
+
}
|
142
|
+
end
|
135
143
|
|
136
144
|
master = {
|
137
145
|
:auth => lambda do |pass|
|
@@ -144,8 +152,9 @@ class SentinalTest < Test::Unit::TestCase
|
|
144
152
|
end
|
145
153
|
}
|
146
154
|
|
147
|
-
RedisMock.start(master
|
148
|
-
RedisMock.start(sentinel
|
155
|
+
RedisMock.start(master) do |master_port|
|
156
|
+
RedisMock.start(sentinel.call(master_port)) do |sen_port|
|
157
|
+
sentinels[0][:port] = sen_port
|
149
158
|
redis = Redis.new(:url => "redis://:foo@master1/15", :sentinels => sentinels, :role => :master)
|
150
159
|
|
151
160
|
assert redis.ping
|
@@ -159,11 +168,13 @@ class SentinalTest < Test::Unit::TestCase
|
|
159
168
|
def test_sentinel_role_mismatch
|
160
169
|
sentinels = [{:host => "127.0.0.1", :port => 26381}]
|
161
170
|
|
162
|
-
sentinel =
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
171
|
+
sentinel = lambda do |port|
|
172
|
+
{
|
173
|
+
:sentinel => lambda do |command, *args|
|
174
|
+
["127.0.0.1", port.to_s]
|
175
|
+
end
|
176
|
+
}
|
177
|
+
end
|
167
178
|
|
168
179
|
master = {
|
169
180
|
:role => lambda do
|
@@ -172,8 +183,9 @@ class SentinalTest < Test::Unit::TestCase
|
|
172
183
|
}
|
173
184
|
|
174
185
|
ex = assert_raise(Redis::ConnectionError) do
|
175
|
-
RedisMock.start(master
|
176
|
-
RedisMock.start(sentinel
|
186
|
+
RedisMock.start(master) do |master_port|
|
187
|
+
RedisMock.start(sentinel.call(master_port)) do |sen_port|
|
188
|
+
sentinels[0][:port] = sen_port
|
177
189
|
redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master)
|
178
190
|
|
179
191
|
assert redis.ping
|
@@ -190,7 +202,7 @@ class SentinalTest < Test::Unit::TestCase
|
|
190
202
|
|
191
203
|
connections = []
|
192
204
|
|
193
|
-
handler = lambda do |id|
|
205
|
+
handler = lambda do |id, port|
|
194
206
|
{
|
195
207
|
:sentinel => lambda do |command, *args|
|
196
208
|
connections << id
|
@@ -198,7 +210,7 @@ class SentinalTest < Test::Unit::TestCase
|
|
198
210
|
if connections.count(id) < 2
|
199
211
|
:close
|
200
212
|
else
|
201
|
-
["127.0.0.1",
|
213
|
+
["127.0.0.1", port.to_s]
|
202
214
|
end
|
203
215
|
end
|
204
216
|
}
|
@@ -210,9 +222,11 @@ class SentinalTest < Test::Unit::TestCase
|
|
210
222
|
end
|
211
223
|
}
|
212
224
|
|
213
|
-
RedisMock.start(master
|
214
|
-
RedisMock.start(handler.call(:s1
|
215
|
-
RedisMock.start(handler.call(:s2
|
225
|
+
RedisMock.start(master) do |master_port|
|
226
|
+
RedisMock.start(handler.call(:s1, master_port)) do |s1_port|
|
227
|
+
RedisMock.start(handler.call(:s2, master_port)) do |s2_port|
|
228
|
+
sentinels[0][:port] = s1_port
|
229
|
+
sentinels[1][:port] = s2_port
|
216
230
|
redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master, :reconnect_attempts => 1)
|
217
231
|
|
218
232
|
assert redis.ping
|
@@ -225,9 +239,9 @@ class SentinalTest < Test::Unit::TestCase
|
|
225
239
|
connections.clear
|
226
240
|
|
227
241
|
ex = assert_raise(Redis::CannotConnectError) do
|
228
|
-
RedisMock.start(master
|
229
|
-
RedisMock.start(handler.call(:s1
|
230
|
-
RedisMock.start(handler.call(:s2
|
242
|
+
RedisMock.start(master) do |master_port|
|
243
|
+
RedisMock.start(handler.call(:s1, master_port)) do |s1_port|
|
244
|
+
RedisMock.start(handler.call(:s2, master_port)) do |s2_port|
|
231
245
|
redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master, :reconnect_attempts => 0)
|
232
246
|
|
233
247
|
assert redis.ping
|
data/test/support/redis_mock.rb
CHANGED
@@ -2,25 +2,21 @@ require "socket"
|
|
2
2
|
|
3
3
|
module RedisMock
|
4
4
|
class Server
|
5
|
-
|
5
|
+
def initialize(options = {}, &block)
|
6
|
+
@server = TCPServer.new(options[:host] || "127.0.0.1", 0)
|
7
|
+
@server.setsockopt(Socket::SOL_SOCKET, Socket::SO_REUSEADDR, true)
|
8
|
+
end
|
6
9
|
|
7
|
-
def
|
8
|
-
@server
|
9
|
-
@server.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR, true)
|
10
|
+
def port
|
11
|
+
@server.addr[1]
|
10
12
|
end
|
11
13
|
|
12
14
|
def start(&block)
|
13
15
|
@thread = Thread.new { run(&block) }
|
14
16
|
end
|
15
17
|
|
16
|
-
# Bail out of @server.accept before closing the socket. This is required
|
17
|
-
# to avoid EADDRINUSE after a couple of iterations.
|
18
18
|
def shutdown
|
19
|
-
@thread.
|
20
|
-
@server.close if @server
|
21
|
-
rescue => ex
|
22
|
-
$stderr.puts "Error closing mock server: #{ex.message}" if VERBOSE
|
23
|
-
$stderr.puts ex.backtrace if VERBOSE
|
19
|
+
@thread.kill
|
24
20
|
end
|
25
21
|
|
26
22
|
def run
|
@@ -35,20 +31,15 @@ module RedisMock
|
|
35
31
|
end
|
36
32
|
end
|
37
33
|
rescue => ex
|
38
|
-
$stderr.puts "Error running mock server: #{ex.message}"
|
39
|
-
$stderr.puts ex.backtrace
|
34
|
+
$stderr.puts "Error running mock server: #{ex.message}"
|
35
|
+
$stderr.puts ex.backtrace
|
40
36
|
retry
|
41
37
|
ensure
|
42
|
-
|
43
|
-
@server.close
|
44
|
-
rescue IOError
|
45
|
-
end
|
38
|
+
@server.close
|
46
39
|
end
|
47
40
|
end
|
48
41
|
end
|
49
42
|
|
50
|
-
MOCK_PORT = 6382
|
51
|
-
|
52
43
|
# Starts a mock Redis server in a thread.
|
53
44
|
#
|
54
45
|
# The server will use the lambda handler passed as argument to handle
|
@@ -59,14 +50,13 @@ module RedisMock
|
|
59
50
|
# # Every connection will be closed immediately
|
60
51
|
# end
|
61
52
|
#
|
62
|
-
def self.start_with_handler(blk, options = {}
|
63
|
-
server = Server.new(
|
53
|
+
def self.start_with_handler(blk, options = {})
|
54
|
+
server = Server.new(options)
|
55
|
+
port = server.port
|
64
56
|
|
65
57
|
begin
|
66
58
|
server.start(&blk)
|
67
|
-
|
68
59
|
yield(port)
|
69
|
-
|
70
60
|
ensure
|
71
61
|
server.shutdown
|
72
62
|
end
|
@@ -77,11 +67,11 @@ module RedisMock
|
|
77
67
|
# The server will reply with a `+OK` to all commands, but you can
|
78
68
|
# customize it by providing a hash. For example:
|
79
69
|
#
|
80
|
-
# RedisMock.start(:ping => lambda { "+PONG" }) do
|
81
|
-
# assert_equal "PONG", Redis.new(:port =>
|
70
|
+
# RedisMock.start(:ping => lambda { "+PONG" }) do |port|
|
71
|
+
# assert_equal "PONG", Redis.new(:port => port).ping
|
82
72
|
# end
|
83
73
|
#
|
84
|
-
def self.start(commands, options = {},
|
74
|
+
def self.start(commands, options = {}, &blk)
|
85
75
|
handler = lambda do |session|
|
86
76
|
while line = session.gets
|
87
77
|
argv = Array.new(line[1..-3].to_i) do
|
@@ -106,8 +96,16 @@ module RedisMock
|
|
106
96
|
break :close
|
107
97
|
elsif response.is_a?(Array)
|
108
98
|
session.write("*%d\r\n" % response.size)
|
109
|
-
|
110
|
-
|
99
|
+
|
100
|
+
response.each do |resp|
|
101
|
+
if resp.is_a?(Array)
|
102
|
+
session.write("*%d\r\n" % resp.size)
|
103
|
+
resp.each do |r|
|
104
|
+
session.write("$%d\r\n%s\r\n" % [r.length, r])
|
105
|
+
end
|
106
|
+
else
|
107
|
+
session.write("$%d\r\n%s\r\n" % [resp.length, resp])
|
108
|
+
end
|
111
109
|
end
|
112
110
|
else
|
113
111
|
session.write(response)
|
@@ -116,6 +114,6 @@ module RedisMock
|
|
116
114
|
end
|
117
115
|
end
|
118
116
|
|
119
|
-
start_with_handler(handler, options,
|
117
|
+
start_with_handler(handler, options, &blk)
|
120
118
|
end
|
121
119
|
end
|
data/test/url_param_test.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: redis
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.2.
|
4
|
+
version: 3.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ezra Zygmuntowicz
|
@@ -16,7 +16,7 @@ authors:
|
|
16
16
|
autorequire:
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
|
-
date: 2015-
|
19
|
+
date: 2015-11-16 00:00:00.000000000 Z
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
22
|
name: rake
|
@@ -32,6 +32,20 @@ dependencies:
|
|
32
32
|
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '0'
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: test-unit
|
37
|
+
requirement: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
type: :development
|
43
|
+
prerelease: false
|
44
|
+
version_requirements: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
35
49
|
description: |2
|
36
50
|
A Ruby client that tries to match Redis' API one-to-one, while still
|
37
51
|
providing an idiomatic interface. It features thread-safety,
|
@@ -134,6 +148,7 @@ files:
|
|
134
148
|
- test/remote_server_control_commands_test.rb
|
135
149
|
- test/scanning_test.rb
|
136
150
|
- test/scripting_test.rb
|
151
|
+
- test/sentinel_command_test.rb
|
137
152
|
- test/sentinel_test.rb
|
138
153
|
- test/sorting_test.rb
|
139
154
|
- test/support/connection/hiredis.rb
|
@@ -168,7 +183,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
183
|
version: '0'
|
169
184
|
requirements: []
|
170
185
|
rubyforge_project:
|
171
|
-
rubygems_version: 2.
|
186
|
+
rubygems_version: 2.4.5.1
|
172
187
|
signing_key:
|
173
188
|
specification_version: 4
|
174
189
|
summary: A Ruby client library for Redis
|
@@ -224,6 +239,7 @@ test_files:
|
|
224
239
|
- test/remote_server_control_commands_test.rb
|
225
240
|
- test/scanning_test.rb
|
226
241
|
- test/scripting_test.rb
|
242
|
+
- test/sentinel_command_test.rb
|
227
243
|
- test/sentinel_test.rb
|
228
244
|
- test/sorting_test.rb
|
229
245
|
- test/support/connection/hiredis.rb
|