redis 4.0.2 → 4.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.travis.yml +2 -2
  4. data/CHANGELOG.md +6 -0
  5. data/lib/redis.rb +97 -11
  6. data/lib/redis/client.rb +19 -11
  7. data/lib/redis/cluster.rb +285 -0
  8. data/lib/redis/cluster/command.rb +81 -0
  9. data/lib/redis/cluster/command_loader.rb +32 -0
  10. data/lib/redis/cluster/key_slot_converter.rb +72 -0
  11. data/lib/redis/cluster/node.rb +104 -0
  12. data/lib/redis/cluster/node_key.rb +35 -0
  13. data/lib/redis/cluster/node_loader.rb +35 -0
  14. data/lib/redis/cluster/option.rb +76 -0
  15. data/lib/redis/cluster/slot.rb +69 -0
  16. data/lib/redis/cluster/slot_loader.rb +47 -0
  17. data/lib/redis/errors.rb +46 -0
  18. data/lib/redis/version.rb +1 -1
  19. data/makefile +54 -16
  20. data/redis.gemspec +2 -1
  21. data/test/client_test.rb +17 -0
  22. data/test/cluster_abnormal_state_test.rb +38 -0
  23. data/test/cluster_blocking_commands_test.rb +15 -0
  24. data/test/cluster_client_internals_test.rb +77 -0
  25. data/test/cluster_client_key_hash_tags_test.rb +88 -0
  26. data/test/cluster_client_options_test.rb +147 -0
  27. data/test/cluster_client_pipelining_test.rb +59 -0
  28. data/test/cluster_client_replicas_test.rb +36 -0
  29. data/test/cluster_client_slots_test.rb +94 -0
  30. data/test/cluster_client_transactions_test.rb +71 -0
  31. data/test/cluster_commands_on_cluster_test.rb +165 -0
  32. data/test/cluster_commands_on_connection_test.rb +40 -0
  33. data/test/cluster_commands_on_geo_test.rb +74 -0
  34. data/test/cluster_commands_on_hashes_test.rb +11 -0
  35. data/test/cluster_commands_on_hyper_log_log_test.rb +17 -0
  36. data/test/cluster_commands_on_keys_test.rb +134 -0
  37. data/test/cluster_commands_on_lists_test.rb +15 -0
  38. data/test/cluster_commands_on_pub_sub_test.rb +101 -0
  39. data/test/cluster_commands_on_scripting_test.rb +56 -0
  40. data/test/cluster_commands_on_server_test.rb +221 -0
  41. data/test/cluster_commands_on_sets_test.rb +39 -0
  42. data/test/cluster_commands_on_sorted_sets_test.rb +35 -0
  43. data/test/cluster_commands_on_streams_test.rb +196 -0
  44. data/test/cluster_commands_on_strings_test.rb +15 -0
  45. data/test/cluster_commands_on_transactions_test.rb +41 -0
  46. data/test/cluster_commands_on_value_types_test.rb +14 -0
  47. data/test/commands_on_hashes_test.rb +2 -14
  48. data/test/commands_on_hyper_log_log_test.rb +2 -14
  49. data/test/commands_on_lists_test.rb +2 -13
  50. data/test/commands_on_sets_test.rb +2 -70
  51. data/test/commands_on_sorted_sets_test.rb +2 -145
  52. data/test/commands_on_strings_test.rb +2 -94
  53. data/test/distributed_blocking_commands_test.rb +8 -0
  54. data/test/distributed_commands_on_hashes_test.rb +16 -3
  55. data/test/distributed_commands_on_hyper_log_log_test.rb +8 -13
  56. data/test/distributed_commands_on_lists_test.rb +4 -5
  57. data/test/distributed_commands_on_sets_test.rb +45 -46
  58. data/test/distributed_commands_on_sorted_sets_test.rb +51 -8
  59. data/test/distributed_commands_on_strings_test.rb +10 -0
  60. data/test/helper.rb +176 -32
  61. data/test/internals_test.rb +13 -0
  62. data/test/lint/blocking_commands.rb +40 -16
  63. data/test/lint/hashes.rb +26 -0
  64. data/test/lint/hyper_log_log.rb +15 -1
  65. data/test/lint/lists.rb +16 -0
  66. data/test/lint/sets.rb +142 -0
  67. data/test/lint/sorted_sets.rb +183 -2
  68. data/test/lint/strings.rb +102 -0
  69. data/test/support/cluster/orchestrator.rb +199 -0
  70. metadata +79 -4
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+ require_relative 'lint/strings'
5
+
6
+ # ruby -w -Itest test/cluster_commands_on_strings_test.rb
7
+ # @see https://redis.io/commands#string
8
+ class TestClusterCommandsOnStrings < Test::Unit::TestCase
9
+ include Helper::Cluster
10
+ include Lint::Strings
11
+
12
+ def mock(*args, &block)
13
+ redis_cluster_mock(*args, &block)
14
+ end
15
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+
5
+ # ruby -w -Itest test/cluster_commands_on_transactions_test.rb
6
+ # @see https://redis.io/commands#transactions
7
+ class TestClusterCommandsOnTransactions < Test::Unit::TestCase
8
+ include Helper::Cluster
9
+
10
+ def test_discard
11
+ assert_raise(Redis::Cluster::AmbiguousNodeError) do
12
+ redis.discard
13
+ end
14
+ end
15
+
16
+ def test_exec
17
+ assert_raise(Redis::Cluster::AmbiguousNodeError) do
18
+ redis.exec
19
+ end
20
+ end
21
+
22
+ def test_multi
23
+ assert_raise(Redis::Cluster::AmbiguousNodeError) do
24
+ redis.multi
25
+ end
26
+ end
27
+
28
+ def test_unwatch
29
+ assert_raise(Redis::Cluster::AmbiguousNodeError) do
30
+ redis.unwatch
31
+ end
32
+ end
33
+
34
+ def test_watch
35
+ assert_raise(Redis::CommandError, "CROSSSLOT Keys in request don't hash to the same slot") do
36
+ redis.watch('key1', 'key2')
37
+ end
38
+
39
+ assert_equal 'OK', redis.watch('{key}1', '{key}2')
40
+ end
41
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'helper'
4
+ require_relative 'lint/value_types'
5
+
6
+ # ruby -w -Itest test/cluster_commands_on_value_types_test.rb
7
+ class TestClusterCommandsOnValueTypes < Test::Unit::TestCase
8
+ include Helper::Cluster
9
+ include Lint::ValueTypes
10
+
11
+ def test_move
12
+ assert_raise(Redis::CommandError) { super }
13
+ end
14
+ end
@@ -1,19 +1,7 @@
1
- require_relative "helper"
2
- require_relative "lint/hashes"
1
+ require_relative 'helper'
2
+ require_relative 'lint/hashes'
3
3
 
4
4
  class TestCommandsOnHashes < Test::Unit::TestCase
5
-
6
5
  include Helper::Client
7
6
  include Lint::Hashes
8
-
9
- def test_mapped_hmget_in_a_pipeline_returns_hash
10
- r.hset("foo", "f1", "s1")
11
- r.hset("foo", "f2", "s2")
12
-
13
- result = r.pipelined do
14
- r.mapped_hmget("foo", "f1", "f2")
15
- end
16
-
17
- assert_equal result[0], { "f1" => "s1", "f2" => "s2" }
18
- end
19
7
  end
@@ -1,19 +1,7 @@
1
- require_relative "helper"
2
- require_relative "lint/hyper_log_log"
1
+ require_relative 'helper'
2
+ require_relative 'lint/hyper_log_log'
3
3
 
4
4
  class TestCommandsOnHyperLogLog < Test::Unit::TestCase
5
-
6
5
  include Helper::Client
7
6
  include Lint::HyperLogLog
8
-
9
- def test_pfmerge
10
- target_version "2.8.9" do
11
- r.pfadd "foo", "s1"
12
- r.pfadd "bar", "s2"
13
-
14
- assert_equal true, r.pfmerge("res", "foo", "bar")
15
- assert_equal 2, r.pfcount("res")
16
- end
17
- end
18
-
19
7
  end
@@ -1,18 +1,7 @@
1
- require_relative "helper"
2
- require_relative "lint/lists"
1
+ require_relative 'helper'
2
+ require_relative 'lint/lists'
3
3
 
4
4
  class TestCommandsOnLists < Test::Unit::TestCase
5
-
6
5
  include Helper::Client
7
6
  include Lint::Lists
8
-
9
- def test_rpoplpush
10
- r.rpush "foo", "s1"
11
- r.rpush "foo", "s2"
12
-
13
- assert_equal "s2", r.rpoplpush("foo", "bar")
14
- assert_equal ["s2"], r.lrange("bar", 0, -1)
15
- assert_equal "s1", r.rpoplpush("foo", "bar")
16
- assert_equal ["s1", "s2"], r.lrange("bar", 0, -1)
17
- end
18
7
  end
@@ -1,75 +1,7 @@
1
- require_relative "helper"
2
- require_relative "lint/sets"
1
+ require_relative 'helper'
2
+ require_relative 'lint/sets'
3
3
 
4
4
  class TestCommandsOnSets < Test::Unit::TestCase
5
-
6
5
  include Helper::Client
7
6
  include Lint::Sets
8
-
9
- def test_smove
10
- r.sadd "foo", "s1"
11
- r.sadd "bar", "s2"
12
-
13
- assert r.smove("foo", "bar", "s1")
14
- assert r.sismember("bar", "s1")
15
- end
16
-
17
- def test_sinter
18
- r.sadd "foo", "s1"
19
- r.sadd "foo", "s2"
20
- r.sadd "bar", "s2"
21
-
22
- assert_equal ["s2"], r.sinter("foo", "bar")
23
- end
24
-
25
- def test_sinterstore
26
- r.sadd "foo", "s1"
27
- r.sadd "foo", "s2"
28
- r.sadd "bar", "s2"
29
-
30
- r.sinterstore("baz", "foo", "bar")
31
-
32
- assert_equal ["s2"], r.smembers("baz")
33
- end
34
-
35
- def test_sunion
36
- r.sadd "foo", "s1"
37
- r.sadd "foo", "s2"
38
- r.sadd "bar", "s2"
39
- r.sadd "bar", "s3"
40
-
41
- assert_equal ["s1", "s2", "s3"], r.sunion("foo", "bar").sort
42
- end
43
-
44
- def test_sunionstore
45
- r.sadd "foo", "s1"
46
- r.sadd "foo", "s2"
47
- r.sadd "bar", "s2"
48
- r.sadd "bar", "s3"
49
-
50
- r.sunionstore("baz", "foo", "bar")
51
-
52
- assert_equal ["s1", "s2", "s3"], r.smembers("baz").sort
53
- end
54
-
55
- def test_sdiff
56
- r.sadd "foo", "s1"
57
- r.sadd "foo", "s2"
58
- r.sadd "bar", "s2"
59
- r.sadd "bar", "s3"
60
-
61
- assert_equal ["s1"], r.sdiff("foo", "bar")
62
- assert_equal ["s3"], r.sdiff("bar", "foo")
63
- end
64
-
65
- def test_sdiffstore
66
- r.sadd "foo", "s1"
67
- r.sadd "foo", "s2"
68
- r.sadd "bar", "s2"
69
- r.sadd "bar", "s3"
70
-
71
- r.sdiffstore("baz", "foo", "bar")
72
-
73
- assert_equal ["s1"], r.smembers("baz")
74
- end
75
7
  end
@@ -1,150 +1,7 @@
1
- require_relative "helper"
2
- require_relative "lint/sorted_sets"
1
+ require_relative 'helper'
2
+ require_relative 'lint/sorted_sets'
3
3
 
4
4
  class TestCommandsOnSortedSets < Test::Unit::TestCase
5
-
6
5
  include Helper::Client
7
6
  include Lint::SortedSets
8
-
9
- def test_zlexcount
10
- target_version "2.8.9" do
11
- r.zadd "foo", 0, "aaren"
12
- r.zadd "foo", 0, "abagael"
13
- r.zadd "foo", 0, "abby"
14
- r.zadd "foo", 0, "abbygail"
15
-
16
- assert_equal 4, r.zlexcount("foo", "[a", "[a\xff")
17
- assert_equal 4, r.zlexcount("foo", "[aa", "[ab\xff")
18
- assert_equal 3, r.zlexcount("foo", "(aaren", "[ab\xff")
19
- assert_equal 2, r.zlexcount("foo", "[aba", "(abbygail")
20
- assert_equal 1, r.zlexcount("foo", "(aaren", "(abby")
21
- end
22
- end
23
-
24
- def test_zrangebylex
25
- target_version "2.8.9" do
26
- r.zadd "foo", 0, "aaren"
27
- r.zadd "foo", 0, "abagael"
28
- r.zadd "foo", 0, "abby"
29
- r.zadd "foo", 0, "abbygail"
30
-
31
- assert_equal ["aaren", "abagael", "abby", "abbygail"], r.zrangebylex("foo", "[a", "[a\xff")
32
- assert_equal ["aaren", "abagael"], r.zrangebylex("foo", "[a", "[a\xff", :limit => [0, 2])
33
- assert_equal ["abby", "abbygail"], r.zrangebylex("foo", "(abb", "(abb\xff")
34
- assert_equal ["abbygail"], r.zrangebylex("foo", "(abby", "(abby\xff")
35
- end
36
- end
37
-
38
- def test_zrevrangebylex
39
- target_version "2.9.9" do
40
- r.zadd "foo", 0, "aaren"
41
- r.zadd "foo", 0, "abagael"
42
- r.zadd "foo", 0, "abby"
43
- r.zadd "foo", 0, "abbygail"
44
-
45
- assert_equal ["abbygail", "abby", "abagael", "aaren"], r.zrevrangebylex("foo", "[a\xff", "[a")
46
- assert_equal ["abbygail", "abby"], r.zrevrangebylex("foo", "[a\xff", "[a", :limit => [0, 2])
47
- assert_equal ["abbygail", "abby"], r.zrevrangebylex("foo", "(abb\xff", "(abb")
48
- assert_equal ["abbygail"], r.zrevrangebylex("foo", "(abby\xff", "(abby")
49
- end
50
- end
51
-
52
- def test_zcount
53
- r.zadd "foo", 1, "s1"
54
- r.zadd "foo", 2, "s2"
55
- r.zadd "foo", 3, "s3"
56
-
57
- assert_equal 2, r.zcount("foo", 2, 3)
58
- end
59
-
60
- def test_zunionstore
61
- r.zadd "foo", 1, "s1"
62
- r.zadd "bar", 2, "s2"
63
- r.zadd "foo", 3, "s3"
64
- r.zadd "bar", 4, "s4"
65
-
66
- assert_equal 4, r.zunionstore("foobar", ["foo", "bar"])
67
- assert_equal ["s1", "s2", "s3", "s4"], r.zrange("foobar", 0, -1)
68
- end
69
-
70
- def test_zunionstore_with_weights
71
- r.zadd "foo", 1, "s1"
72
- r.zadd "foo", 3, "s3"
73
- r.zadd "bar", 20, "s2"
74
- r.zadd "bar", 40, "s4"
75
-
76
- assert_equal 4, r.zunionstore("foobar", ["foo", "bar"])
77
- assert_equal ["s1", "s3", "s2", "s4"], r.zrange("foobar", 0, -1)
78
-
79
- assert_equal 4, r.zunionstore("foobar", ["foo", "bar"], :weights => [10, 1])
80
- assert_equal ["s1", "s2", "s3", "s4"], r.zrange("foobar", 0, -1)
81
- end
82
-
83
- def test_zunionstore_with_aggregate
84
- r.zadd "foo", 1, "s1"
85
- r.zadd "foo", 2, "s2"
86
- r.zadd "bar", 4, "s2"
87
- r.zadd "bar", 3, "s3"
88
-
89
- assert_equal 3, r.zunionstore("foobar", ["foo", "bar"])
90
- assert_equal ["s1", "s3", "s2"], r.zrange("foobar", 0, -1)
91
-
92
- assert_equal 3, r.zunionstore("foobar", ["foo", "bar"], :aggregate => :min)
93
- assert_equal ["s1", "s2", "s3"], r.zrange("foobar", 0, -1)
94
-
95
- assert_equal 3, r.zunionstore("foobar", ["foo", "bar"], :aggregate => :max)
96
- assert_equal ["s1", "s3", "s2"], r.zrange("foobar", 0, -1)
97
- end
98
-
99
- def test_zinterstore
100
- r.zadd "foo", 1, "s1"
101
- r.zadd "bar", 2, "s1"
102
- r.zadd "foo", 3, "s3"
103
- r.zadd "bar", 4, "s4"
104
-
105
- assert_equal 1, r.zinterstore("foobar", ["foo", "bar"])
106
- assert_equal ["s1"], r.zrange("foobar", 0, -1)
107
- end
108
-
109
- def test_zinterstore_with_weights
110
- r.zadd "foo", 1, "s1"
111
- r.zadd "foo", 2, "s2"
112
- r.zadd "foo", 3, "s3"
113
- r.zadd "bar", 20, "s2"
114
- r.zadd "bar", 30, "s3"
115
- r.zadd "bar", 40, "s4"
116
-
117
- assert_equal 2, r.zinterstore("foobar", ["foo", "bar"])
118
- assert_equal ["s2", "s3"], r.zrange("foobar", 0, -1)
119
-
120
- assert_equal 2, r.zinterstore("foobar", ["foo", "bar"], :weights => [10, 1])
121
- assert_equal ["s2", "s3"], r.zrange("foobar", 0, -1)
122
-
123
- assert_equal 40.0, r.zscore("foobar", "s2")
124
- assert_equal 60.0, r.zscore("foobar", "s3")
125
- end
126
-
127
- def test_zinterstore_with_aggregate
128
- r.zadd "foo", 1, "s1"
129
- r.zadd "foo", 2, "s2"
130
- r.zadd "foo", 3, "s3"
131
- r.zadd "bar", 20, "s2"
132
- r.zadd "bar", 30, "s3"
133
- r.zadd "bar", 40, "s4"
134
-
135
- assert_equal 2, r.zinterstore("foobar", ["foo", "bar"])
136
- assert_equal ["s2", "s3"], r.zrange("foobar", 0, -1)
137
- assert_equal 22.0, r.zscore("foobar", "s2")
138
- assert_equal 33.0, r.zscore("foobar", "s3")
139
-
140
- assert_equal 2, r.zinterstore("foobar", ["foo", "bar"], :aggregate => :min)
141
- assert_equal ["s2", "s3"], r.zrange("foobar", 0, -1)
142
- assert_equal 2.0, r.zscore("foobar", "s2")
143
- assert_equal 3.0, r.zscore("foobar", "s3")
144
-
145
- assert_equal 2, r.zinterstore("foobar", ["foo", "bar"], :aggregate => :max)
146
- assert_equal ["s2", "s3"], r.zrange("foobar", 0, -1)
147
- assert_equal 20.0, r.zscore("foobar", "s2")
148
- assert_equal 30.0, r.zscore("foobar", "s3")
149
- end
150
7
  end
@@ -1,99 +1,7 @@
1
- require_relative "helper"
2
- require_relative "lint/strings"
1
+ require_relative 'helper'
2
+ require_relative 'lint/strings'
3
3
 
4
4
  class TestCommandsOnStrings < Test::Unit::TestCase
5
-
6
5
  include Helper::Client
7
6
  include Lint::Strings
8
-
9
- def test_mget
10
- r.set("foo", "s1")
11
- r.set("bar", "s2")
12
-
13
- assert_equal ["s1", "s2"] , r.mget("foo", "bar")
14
- assert_equal ["s1", "s2", nil], r.mget("foo", "bar", "baz")
15
- end
16
-
17
- def test_mget_mapped
18
- r.set("foo", "s1")
19
- r.set("bar", "s2")
20
-
21
- response = r.mapped_mget("foo", "bar")
22
-
23
- assert_equal "s1", response["foo"]
24
- assert_equal "s2", response["bar"]
25
-
26
- response = r.mapped_mget("foo", "bar", "baz")
27
-
28
- assert_equal "s1", response["foo"]
29
- assert_equal "s2", response["bar"]
30
- assert_equal nil , response["baz"]
31
- end
32
-
33
- def test_mapped_mget_in_a_pipeline_returns_hash
34
- r.set("foo", "s1")
35
- r.set("bar", "s2")
36
-
37
- result = r.pipelined do
38
- r.mapped_mget("foo", "bar")
39
- end
40
-
41
- assert_equal result[0], { "foo" => "s1", "bar" => "s2" }
42
- end
43
-
44
- def test_mset
45
- r.mset(:foo, "s1", :bar, "s2")
46
-
47
- assert_equal "s1", r.get("foo")
48
- assert_equal "s2", r.get("bar")
49
- end
50
-
51
- def test_mset_mapped
52
- r.mapped_mset(:foo => "s1", :bar => "s2")
53
-
54
- assert_equal "s1", r.get("foo")
55
- assert_equal "s2", r.get("bar")
56
- end
57
-
58
- def test_msetnx
59
- r.set("foo", "s1")
60
- assert_equal false, r.msetnx(:foo, "s2", :bar, "s3")
61
- assert_equal "s1", r.get("foo")
62
- assert_equal nil, r.get("bar")
63
-
64
- r.del("foo")
65
- assert_equal true, r.msetnx(:foo, "s2", :bar, "s3")
66
- assert_equal "s2", r.get("foo")
67
- assert_equal "s3", r.get("bar")
68
- end
69
-
70
- def test_msetnx_mapped
71
- r.set("foo", "s1")
72
- assert_equal false, r.mapped_msetnx(:foo => "s2", :bar => "s3")
73
- assert_equal "s1", r.get("foo")
74
- assert_equal nil, r.get("bar")
75
-
76
- r.del("foo")
77
- assert_equal true, r.mapped_msetnx(:foo => "s2", :bar => "s3")
78
- assert_equal "s2", r.get("foo")
79
- assert_equal "s3", r.get("bar")
80
- end
81
-
82
- def test_bitop
83
- with_external_encoding("UTF-8") do
84
- target_version "2.5.10" do
85
- r.set("foo", "a")
86
- r.set("bar", "b")
87
-
88
- r.bitop(:and, "foo&bar", "foo", "bar")
89
- assert_equal "\x60", r.get("foo&bar")
90
- r.bitop(:or, "foo|bar", "foo", "bar")
91
- assert_equal "\x63", r.get("foo|bar")
92
- r.bitop(:xor, "foo^bar", "foo", "bar")
93
- assert_equal "\x03", r.get("foo^bar")
94
- r.bitop(:not, "~foo", "foo")
95
- assert_equal "\x9E", r.get("~foo")
96
- end
97
- end
98
- end
99
7
  end