redis 4.0.1 → 4.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +3 -0
- data/.travis.yml +17 -29
- data/.travis/Gemfile +5 -0
- data/CHANGELOG.md +29 -0
- data/Gemfile +5 -0
- data/README.md +1 -1
- data/bin/build +71 -0
- data/lib/redis.rb +198 -12
- data/lib/redis/client.rb +26 -12
- data/lib/redis/cluster.rb +285 -0
- data/lib/redis/cluster/command.rb +81 -0
- data/lib/redis/cluster/command_loader.rb +32 -0
- data/lib/redis/cluster/key_slot_converter.rb +72 -0
- data/lib/redis/cluster/node.rb +104 -0
- data/lib/redis/cluster/node_key.rb +35 -0
- data/lib/redis/cluster/node_loader.rb +35 -0
- data/lib/redis/cluster/option.rb +76 -0
- data/lib/redis/cluster/slot.rb +69 -0
- data/lib/redis/cluster/slot_loader.rb +47 -0
- data/lib/redis/connection/ruby.rb +5 -2
- data/lib/redis/distributed.rb +10 -2
- data/lib/redis/errors.rb +46 -0
- data/lib/redis/pipeline.rb +9 -1
- data/lib/redis/version.rb +1 -1
- data/makefile +54 -22
- data/redis.gemspec +2 -1
- data/test/client_test.rb +17 -0
- data/test/cluster_abnormal_state_test.rb +38 -0
- data/test/cluster_blocking_commands_test.rb +15 -0
- data/test/cluster_client_internals_test.rb +77 -0
- data/test/cluster_client_key_hash_tags_test.rb +88 -0
- data/test/cluster_client_options_test.rb +147 -0
- data/test/cluster_client_pipelining_test.rb +59 -0
- data/test/cluster_client_replicas_test.rb +36 -0
- data/test/cluster_client_slots_test.rb +94 -0
- data/test/cluster_client_transactions_test.rb +71 -0
- data/test/cluster_commands_on_cluster_test.rb +165 -0
- data/test/cluster_commands_on_connection_test.rb +40 -0
- data/test/cluster_commands_on_geo_test.rb +74 -0
- data/test/cluster_commands_on_hashes_test.rb +11 -0
- data/test/cluster_commands_on_hyper_log_log_test.rb +17 -0
- data/test/cluster_commands_on_keys_test.rb +134 -0
- data/test/cluster_commands_on_lists_test.rb +15 -0
- data/test/cluster_commands_on_pub_sub_test.rb +101 -0
- data/test/cluster_commands_on_scripting_test.rb +56 -0
- data/test/cluster_commands_on_server_test.rb +221 -0
- data/test/cluster_commands_on_sets_test.rb +39 -0
- data/test/cluster_commands_on_sorted_sets_test.rb +35 -0
- data/test/cluster_commands_on_streams_test.rb +196 -0
- data/test/cluster_commands_on_strings_test.rb +15 -0
- data/test/cluster_commands_on_transactions_test.rb +41 -0
- data/test/cluster_commands_on_value_types_test.rb +14 -0
- data/test/commands_on_geo_test.rb +116 -0
- data/test/commands_on_hashes_test.rb +2 -14
- data/test/commands_on_hyper_log_log_test.rb +2 -14
- data/test/commands_on_lists_test.rb +2 -13
- data/test/commands_on_sets_test.rb +2 -70
- data/test/commands_on_sorted_sets_test.rb +2 -145
- data/test/commands_on_strings_test.rb +2 -94
- data/test/commands_on_value_types_test.rb +36 -0
- data/test/distributed_blocking_commands_test.rb +8 -0
- data/test/distributed_commands_on_hashes_test.rb +16 -3
- data/test/distributed_commands_on_hyper_log_log_test.rb +8 -13
- data/test/distributed_commands_on_lists_test.rb +4 -5
- data/test/distributed_commands_on_sets_test.rb +45 -46
- data/test/distributed_commands_on_sorted_sets_test.rb +51 -8
- data/test/distributed_commands_on_strings_test.rb +10 -0
- data/test/distributed_commands_on_value_types_test.rb +36 -0
- data/test/helper.rb +176 -32
- data/test/internals_test.rb +20 -1
- data/test/lint/blocking_commands.rb +40 -16
- data/test/lint/hashes.rb +41 -0
- data/test/lint/hyper_log_log.rb +15 -1
- data/test/lint/lists.rb +16 -0
- data/test/lint/sets.rb +142 -0
- data/test/lint/sorted_sets.rb +183 -2
- data/test/lint/strings.rb +102 -0
- data/test/pipelining_commands_test.rb +8 -0
- data/test/support/cluster/orchestrator.rb +199 -0
- data/test/support/redis_mock.rb +1 -1
- data/test/transactions_test.rb +10 -0
- metadata +81 -2
@@ -0,0 +1,147 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
# ruby -w -Itest test/cluster_client_options_test.rb
|
6
|
+
class TestClusterClientOptions < Test::Unit::TestCase
|
7
|
+
include Helper::Cluster
|
8
|
+
|
9
|
+
def test_option_class
|
10
|
+
option = Redis::Cluster::Option.new(cluster: %w[rediss://127.0.0.1:7000], replica: true)
|
11
|
+
assert_equal({ '127.0.0.1:7000' => { url: 'rediss://127.0.0.1:7000' } }, option.per_node_key)
|
12
|
+
assert_equal true, option.secure?
|
13
|
+
assert_equal true, option.use_replica?
|
14
|
+
|
15
|
+
option = Redis::Cluster::Option.new(cluster: %w[redis://127.0.0.1:7000], replica: false)
|
16
|
+
assert_equal({ '127.0.0.1:7000' => { url: 'redis://127.0.0.1:7000' } }, option.per_node_key)
|
17
|
+
assert_equal false, option.secure?
|
18
|
+
assert_equal false, option.use_replica?
|
19
|
+
|
20
|
+
option = Redis::Cluster::Option.new(cluster: %w[redis://127.0.0.1:7000])
|
21
|
+
assert_equal({ '127.0.0.1:7000' => { url: 'redis://127.0.0.1:7000' } }, option.per_node_key)
|
22
|
+
assert_equal false, option.secure?
|
23
|
+
assert_equal false, option.use_replica?
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_client_accepts_valid_node_configs
|
27
|
+
nodes = ['redis://127.0.0.1:7000',
|
28
|
+
'redis://127.0.0.1:7001',
|
29
|
+
{ host: '127.0.0.1', port: '7002' },
|
30
|
+
{ 'host' => '127.0.0.1', port: 7003 },
|
31
|
+
'redis://127.0.0.1:7004',
|
32
|
+
'redis://127.0.0.1:7005']
|
33
|
+
|
34
|
+
assert_nothing_raised do
|
35
|
+
build_another_client(cluster: nodes)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_client_accepts_valid_options
|
40
|
+
assert_nothing_raised do
|
41
|
+
build_another_client(timeout: 1.0)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_client_ignores_invalid_options
|
46
|
+
assert_nothing_raised do
|
47
|
+
build_another_client(invalid_option: true)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_client_works_even_if_so_many_unavailable_nodes_specified
|
52
|
+
nodes = (6001..7005).map { |port| "redis://127.0.0.1:#{port}" }
|
53
|
+
redis = build_another_client(cluster: nodes)
|
54
|
+
|
55
|
+
assert_equal 'PONG', redis.ping
|
56
|
+
end
|
57
|
+
|
58
|
+
def test_client_does_not_accept_db_specified_url
|
59
|
+
assert_raise(Redis::CannotConnectError, 'Could not connect to any nodes') do
|
60
|
+
build_another_client(cluster: ['redis://127.0.0.1:7000/1/namespace'])
|
61
|
+
end
|
62
|
+
|
63
|
+
assert_raise(Redis::CannotConnectError, 'Could not connect to any nodes') do
|
64
|
+
build_another_client(cluster: [{ host: '127.0.0.1', port: '7000' }], db: 1)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_client_does_not_accept_unconnectable_node_url_only
|
69
|
+
nodes = ['redis://127.0.0.1:7006']
|
70
|
+
|
71
|
+
assert_raise(Redis::CannotConnectError, 'Could not connect to any nodes') do
|
72
|
+
build_another_client(cluster: nodes)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_client_accepts_unconnectable_node_url_included
|
77
|
+
nodes = ['redis://127.0.0.1:7000', 'redis://127.0.0.1:7006']
|
78
|
+
|
79
|
+
assert_nothing_raised(Redis::CannotConnectError, 'Could not connect to any nodes') do
|
80
|
+
build_another_client(cluster: nodes)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def test_client_does_not_accept_http_scheme_url
|
85
|
+
nodes = ['http://127.0.0.1:80']
|
86
|
+
|
87
|
+
assert_raise(Redis::InvalidClientOptionError, "invalid uri scheme 'http'") do
|
88
|
+
build_another_client(cluster: nodes)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_client_does_not_accept_blank_included_config
|
93
|
+
nodes = ['']
|
94
|
+
|
95
|
+
assert_raise(Redis::InvalidClientOptionError, "invalid uri scheme ''") do
|
96
|
+
build_another_client(cluster: nodes)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_client_does_not_accept_bool_included_config
|
101
|
+
nodes = [true]
|
102
|
+
|
103
|
+
assert_raise(Redis::InvalidClientOptionError, "invalid uri scheme ''") do
|
104
|
+
build_another_client(cluster: nodes)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_client_does_not_accept_nil_included_config
|
109
|
+
nodes = [nil]
|
110
|
+
|
111
|
+
assert_raise(Redis::InvalidClientOptionError, "invalid uri scheme ''") do
|
112
|
+
build_another_client(cluster: nodes)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_client_does_not_accept_array_included_config
|
117
|
+
nodes = [[]]
|
118
|
+
|
119
|
+
assert_raise(Redis::InvalidClientOptionError, "invalid uri scheme ''") do
|
120
|
+
build_another_client(cluster: nodes)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_client_does_not_accept_empty_hash_included_config
|
125
|
+
nodes = [{}]
|
126
|
+
|
127
|
+
assert_raise(Redis::InvalidClientOptionError, 'Redis option of `cluster` must includes `:host` and `:port` keys') do
|
128
|
+
build_another_client(cluster: nodes)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def test_client_does_not_accept_object_included_config
|
133
|
+
nodes = [Object.new]
|
134
|
+
|
135
|
+
assert_raise(Redis::InvalidClientOptionError, 'Redis Cluster node config must includes String or Hash') do
|
136
|
+
build_another_client(cluster: nodes)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def test_client_does_not_accept_not_array_config
|
141
|
+
nodes = :not_array
|
142
|
+
|
143
|
+
assert_raise(Redis::InvalidClientOptionError, 'Redis Cluster node config must be Array') do
|
144
|
+
build_another_client(cluster: nodes)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
# ruby -w -Itest test/cluster_client_pipelining_test.rb
|
6
|
+
class TestClusterClientPipelining < Test::Unit::TestCase
|
7
|
+
include Helper::Cluster
|
8
|
+
|
9
|
+
def test_pipelining_with_a_hash_tag
|
10
|
+
p1 = p2 = p3 = p4 = p5 = p6 = nil
|
11
|
+
|
12
|
+
redis.pipelined do |r|
|
13
|
+
r.set('{Presidents.of.USA}:1', 'George Washington')
|
14
|
+
r.set('{Presidents.of.USA}:2', 'John Adams')
|
15
|
+
r.set('{Presidents.of.USA}:3', 'Thomas Jefferson')
|
16
|
+
r.set('{Presidents.of.USA}:4', 'James Madison')
|
17
|
+
r.set('{Presidents.of.USA}:5', 'James Monroe')
|
18
|
+
r.set('{Presidents.of.USA}:6', 'John Quincy Adams')
|
19
|
+
|
20
|
+
p1 = r.get('{Presidents.of.USA}:1')
|
21
|
+
p2 = r.get('{Presidents.of.USA}:2')
|
22
|
+
p3 = r.get('{Presidents.of.USA}:3')
|
23
|
+
p4 = r.get('{Presidents.of.USA}:4')
|
24
|
+
p5 = r.get('{Presidents.of.USA}:5')
|
25
|
+
p6 = r.get('{Presidents.of.USA}:6')
|
26
|
+
end
|
27
|
+
|
28
|
+
[p1, p2, p3, p4, p5, p6].each do |actual|
|
29
|
+
assert_true actual.is_a?(Redis::Future)
|
30
|
+
end
|
31
|
+
|
32
|
+
assert_equal('George Washington', p1.value)
|
33
|
+
assert_equal('John Adams', p2.value)
|
34
|
+
assert_equal('Thomas Jefferson', p3.value)
|
35
|
+
assert_equal('James Madison', p4.value)
|
36
|
+
assert_equal('James Monroe', p5.value)
|
37
|
+
assert_equal('John Quincy Adams', p6.value)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_pipelining_without_hash_tags
|
41
|
+
assert_raise(Redis::Cluster::CrossSlotPipeliningError) do
|
42
|
+
redis.pipelined do
|
43
|
+
redis.set(:a, 1)
|
44
|
+
redis.set(:b, 2)
|
45
|
+
redis.set(:c, 3)
|
46
|
+
redis.set(:d, 4)
|
47
|
+
redis.set(:e, 5)
|
48
|
+
redis.set(:f, 6)
|
49
|
+
|
50
|
+
redis.get(:a)
|
51
|
+
redis.get(:b)
|
52
|
+
redis.get(:c)
|
53
|
+
redis.get(:d)
|
54
|
+
redis.get(:e)
|
55
|
+
redis.get(:f)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
# ruby -w -Itest test/cluster_client_replicas_test.rb
|
6
|
+
class TestClusterClientReplicas < Test::Unit::TestCase
|
7
|
+
include Helper::Cluster
|
8
|
+
|
9
|
+
def test_client_can_command_with_replica
|
10
|
+
r = build_another_client(replica: true)
|
11
|
+
|
12
|
+
100.times do |i|
|
13
|
+
assert_equal 'OK', r.set("key#{i}", i)
|
14
|
+
end
|
15
|
+
|
16
|
+
100.times do |i|
|
17
|
+
assert_equal i.to_s, r.get("key#{i}")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_client_can_flush_with_replica
|
22
|
+
r = build_another_client(replica: true)
|
23
|
+
|
24
|
+
assert_equal 'OK', r.flushall
|
25
|
+
assert_equal 'OK', r.flushdb
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_some_reference_commands_are_sent_to_slaves_if_needed
|
29
|
+
r = build_another_client(replica: true)
|
30
|
+
|
31
|
+
5.times { |i| r.set("key#{i}", i) }
|
32
|
+
|
33
|
+
assert_equal %w[key0 key1 key2 key3 key4], r.keys
|
34
|
+
assert_equal 5, r.dbsize
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
# ruby -w -Itest test/cluster_client_slots_test.rb
|
6
|
+
class TestClusterClientSlots < Test::Unit::TestCase
|
7
|
+
include Helper::Cluster
|
8
|
+
|
9
|
+
def test_slot_class
|
10
|
+
slot = Redis::Cluster::Slot.new('127.0.0.1:7000' => 1..10)
|
11
|
+
|
12
|
+
assert_equal false, slot.exists?(0)
|
13
|
+
assert_equal true, slot.exists?(1)
|
14
|
+
assert_equal true, slot.exists?(10)
|
15
|
+
assert_equal false, slot.exists?(11)
|
16
|
+
|
17
|
+
assert_equal nil, slot.find_node_key_of_master(0)
|
18
|
+
assert_equal nil, slot.find_node_key_of_slave(0)
|
19
|
+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(1)
|
20
|
+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(1)
|
21
|
+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(10)
|
22
|
+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(10)
|
23
|
+
assert_equal nil, slot.find_node_key_of_master(11)
|
24
|
+
assert_equal nil, slot.find_node_key_of_slave(11)
|
25
|
+
|
26
|
+
assert_equal nil, slot.put(1, '127.0.0.1:7001')
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_slot_class_with_node_flags_and_replicas
|
30
|
+
slot = Redis::Cluster::Slot.new({ '127.0.0.1:7000' => 1..10, '127.0.0.1:7001' => 1..10 },
|
31
|
+
{ '127.0.0.1:7000' => 'master', '127.0.0.1:7001' => 'slave' },
|
32
|
+
true)
|
33
|
+
|
34
|
+
assert_equal false, slot.exists?(0)
|
35
|
+
assert_equal true, slot.exists?(1)
|
36
|
+
assert_equal true, slot.exists?(10)
|
37
|
+
assert_equal false, slot.exists?(11)
|
38
|
+
|
39
|
+
assert_equal nil, slot.find_node_key_of_master(0)
|
40
|
+
assert_equal nil, slot.find_node_key_of_slave(0)
|
41
|
+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(1)
|
42
|
+
assert_equal '127.0.0.1:7001', slot.find_node_key_of_slave(1)
|
43
|
+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(10)
|
44
|
+
assert_equal '127.0.0.1:7001', slot.find_node_key_of_slave(10)
|
45
|
+
assert_equal nil, slot.find_node_key_of_master(11)
|
46
|
+
assert_equal nil, slot.find_node_key_of_slave(11)
|
47
|
+
|
48
|
+
assert_equal nil, slot.put(1, '127.0.0.1:7002')
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_slot_class_with_node_flags_and_without_replicas
|
52
|
+
slot = Redis::Cluster::Slot.new({ '127.0.0.1:7000' => 1..10, '127.0.0.1:7001' => 1..10 },
|
53
|
+
{ '127.0.0.1:7000' => 'master', '127.0.0.1:7001' => 'slave' },
|
54
|
+
false)
|
55
|
+
|
56
|
+
assert_equal false, slot.exists?(0)
|
57
|
+
assert_equal true, slot.exists?(1)
|
58
|
+
assert_equal true, slot.exists?(10)
|
59
|
+
assert_equal false, slot.exists?(11)
|
60
|
+
|
61
|
+
assert_equal nil, slot.find_node_key_of_master(0)
|
62
|
+
assert_equal nil, slot.find_node_key_of_slave(0)
|
63
|
+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(1)
|
64
|
+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(1)
|
65
|
+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_master(10)
|
66
|
+
assert_equal '127.0.0.1:7000', slot.find_node_key_of_slave(10)
|
67
|
+
assert_equal nil, slot.find_node_key_of_master(11)
|
68
|
+
assert_equal nil, slot.find_node_key_of_slave(11)
|
69
|
+
|
70
|
+
assert_equal nil, slot.put(1, '127.0.0.1:7002')
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_slot_class_with_empty_slots
|
74
|
+
slot = Redis::Cluster::Slot.new({})
|
75
|
+
|
76
|
+
assert_equal false, slot.exists?(0)
|
77
|
+
assert_equal false, slot.exists?(1)
|
78
|
+
|
79
|
+
assert_equal nil, slot.find_node_key_of_master(0)
|
80
|
+
assert_equal nil, slot.find_node_key_of_slave(0)
|
81
|
+
assert_equal nil, slot.find_node_key_of_master(1)
|
82
|
+
assert_equal nil, slot.find_node_key_of_slave(1)
|
83
|
+
|
84
|
+
assert_equal nil, slot.put(1, '127.0.0.1:7001')
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_redirection_when_slot_is_resharding
|
88
|
+
100.times { |i| redis.set("{key}#{i}", i) }
|
89
|
+
|
90
|
+
redis_cluster_resharding(12539, src: '127.0.0.1:7002', dest: '127.0.0.1:7000') do
|
91
|
+
100.times { |i| assert_equal i.to_s, redis.get("{key}#{i}") }
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
# ruby -w -Itest test/cluster_client_transactions_test.rb
|
6
|
+
class TestClusterClientTransactions < Test::Unit::TestCase
|
7
|
+
include Helper::Cluster
|
8
|
+
|
9
|
+
def test_transaction_with_hash_tag
|
10
|
+
rc1 = redis
|
11
|
+
rc2 = build_another_client
|
12
|
+
|
13
|
+
rc1.multi do |cli|
|
14
|
+
100.times { |i| cli.set("{key}#{i}", i) }
|
15
|
+
end
|
16
|
+
|
17
|
+
100.times { |i| assert_equal i.to_s, rc1.get("{key}#{i}") }
|
18
|
+
100.times { |i| assert_equal i.to_s, rc2.get("{key}#{i}") }
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_transaction_without_hash_tag
|
22
|
+
rc1 = redis
|
23
|
+
rc2 = build_another_client
|
24
|
+
|
25
|
+
assert_raise(Redis::Cluster::CrossSlotPipeliningError) do
|
26
|
+
rc1.multi do |cli|
|
27
|
+
100.times { |i| cli.set("key#{i}", i) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
100.times { |i| assert_equal nil, rc1.get("key#{i}") }
|
32
|
+
100.times { |i| assert_equal nil, rc2.get("key#{i}") }
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_transaction_with_replicas
|
36
|
+
rc1 = build_another_client(replica: true)
|
37
|
+
rc2 = build_another_client(replica: true)
|
38
|
+
|
39
|
+
rc1.multi do |cli|
|
40
|
+
100.times { |i| cli.set("{key}#{i}", i) }
|
41
|
+
end
|
42
|
+
|
43
|
+
sleep 0.1
|
44
|
+
|
45
|
+
100.times { |i| assert_equal i.to_s, rc1.get("{key}#{i}") }
|
46
|
+
100.times { |i| assert_equal i.to_s, rc2.get("{key}#{i}") }
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_transaction_with_watch
|
50
|
+
rc1 = redis
|
51
|
+
rc2 = build_another_client
|
52
|
+
|
53
|
+
rc1.set('{key}1', 100)
|
54
|
+
rc1.watch('{key}1')
|
55
|
+
|
56
|
+
rc2.set('{key}1', 200)
|
57
|
+
val = rc1.get('{key}1').to_i
|
58
|
+
val += 1
|
59
|
+
|
60
|
+
rc1.multi do |cli|
|
61
|
+
cli.set('{key}1', val)
|
62
|
+
cli.set('{key}2', 300)
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_equal '200', rc1.get('{key}1')
|
66
|
+
assert_equal '200', rc2.get('{key}1')
|
67
|
+
|
68
|
+
assert_equal nil, rc1.get('{key}2')
|
69
|
+
assert_equal nil, rc2.get('{key}2')
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'helper'
|
4
|
+
|
5
|
+
# ruby -w -Itest test/cluster_commands_on_cluster_test.rb
|
6
|
+
# @see https://redis.io/commands#cluster
|
7
|
+
class TestClusterCommandsOnCluster < Test::Unit::TestCase
|
8
|
+
include Helper::Cluster
|
9
|
+
|
10
|
+
def test_cluster_addslots
|
11
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER ADDSLOTS command should be...') do
|
12
|
+
redis.cluster(:addslots, 0, 1, 2)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_cluster_count_failure_reports
|
17
|
+
assert_raise(Redis::CommandError, 'ERR Unknown node unknown-node-id') do
|
18
|
+
redis.cluster('count-failure-reports', 'unknown-node-id')
|
19
|
+
end
|
20
|
+
|
21
|
+
node_id = redis.cluster(:nodes).first.fetch('node_id')
|
22
|
+
assert_true(redis.cluster('count-failure-reports', node_id) >= 0)
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_cluster_countkeysinslot
|
26
|
+
assert_true(redis.cluster(:countkeysinslot, 0) >= 0)
|
27
|
+
assert_true(redis.cluster(:countkeysinslot, 16383) >= 0)
|
28
|
+
|
29
|
+
assert_raise(Redis::CommandError, 'ERR Invalid slot') do
|
30
|
+
redis.cluster(:countkeysinslot, -1)
|
31
|
+
end
|
32
|
+
|
33
|
+
assert_raise(Redis::CommandError, 'ERR Invalid slot') do
|
34
|
+
redis.cluster(:countkeysinslot, 16384)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_cluster_delslots
|
39
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER DELSLOTS command should be...') do
|
40
|
+
redis.cluster(:delslots, 0, 1, 2)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_cluster_failover
|
45
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER FAILOVER command should be...') do
|
46
|
+
redis.cluster(:failover, 'FORCE')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_cluster_forget
|
51
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER FORGET command should be...') do
|
52
|
+
redis.cluster(:forget, 'unknown-node-id')
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_cluster_getkeysinslot
|
57
|
+
assert_instance_of Array, redis.cluster(:getkeysinslot, 0, 3)
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_cluster_info
|
61
|
+
info = redis.cluster(:info)
|
62
|
+
|
63
|
+
assert_equal '3', info.fetch('cluster_size')
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_cluster_keyslot
|
67
|
+
assert_equal Redis::Cluster::KeySlotConverter.convert('hogehoge'), redis.cluster(:keyslot, 'hogehoge')
|
68
|
+
assert_equal Redis::Cluster::KeySlotConverter.convert('12345'), redis.cluster(:keyslot, '12345')
|
69
|
+
assert_equal Redis::Cluster::KeySlotConverter.convert('foo'), redis.cluster(:keyslot, 'boo{foo}woo')
|
70
|
+
assert_equal Redis::Cluster::KeySlotConverter.convert('antirez.is.cool'), redis.cluster(:keyslot, 'antirez.is.cool')
|
71
|
+
assert_equal Redis::Cluster::KeySlotConverter.convert(''), redis.cluster(:keyslot, '')
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_cluster_meet
|
75
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER MEET command should be...') do
|
76
|
+
redis.cluster(:meet, '127.0.0.1', 11211)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_cluster_nodes
|
81
|
+
cluster_nodes = redis.cluster(:nodes)
|
82
|
+
sample_node = cluster_nodes.first
|
83
|
+
|
84
|
+
assert_equal 6, cluster_nodes.length
|
85
|
+
assert_equal true, sample_node.key?('node_id')
|
86
|
+
assert_equal true, sample_node.key?('ip_port')
|
87
|
+
assert_equal true, sample_node.key?('flags')
|
88
|
+
assert_equal true, sample_node.key?('master_node_id')
|
89
|
+
assert_equal true, sample_node.key?('ping_sent')
|
90
|
+
assert_equal true, sample_node.key?('pong_recv')
|
91
|
+
assert_equal true, sample_node.key?('config_epoch')
|
92
|
+
assert_equal true, sample_node.key?('link_state')
|
93
|
+
assert_equal true, sample_node.key?('slots')
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_cluster_replicate
|
97
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER REPLICATE command should be...') do
|
98
|
+
redis.cluster(:replicate)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_cluster_reset
|
103
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER RESET command should be...') do
|
104
|
+
redis.cluster(:reset)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_cluster_saveconfig
|
109
|
+
assert_equal 'OK', redis.cluster(:saveconfig)
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_cluster_set_config_epoch
|
113
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER SET-CONFIG-EPOCH command should be...') do
|
114
|
+
redis.cluster('set-config-epoch')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_cluster_setslot
|
119
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'CLUSTER SETSLOT command should be...') do
|
120
|
+
redis.cluster(:setslot)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def test_cluster_slaves
|
125
|
+
cluster_nodes = redis.cluster(:nodes)
|
126
|
+
|
127
|
+
sample_master_node_id = cluster_nodes.find { |n| n.fetch('master_node_id') == '-' }.fetch('node_id')
|
128
|
+
sample_slave_node_id = cluster_nodes.find { |n| n.fetch('master_node_id') != '-' }.fetch('node_id')
|
129
|
+
|
130
|
+
assert_equal 'slave', redis.cluster(:slaves, sample_master_node_id).first.fetch('flags').first
|
131
|
+
assert_raise(Redis::CommandError, 'ERR The specified node is not a master') do
|
132
|
+
redis.cluster(:slaves, sample_slave_node_id)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def test_cluster_slots
|
137
|
+
slots = redis.cluster(:slots)
|
138
|
+
sample_slot = slots.first
|
139
|
+
|
140
|
+
assert_equal 3, slots.length
|
141
|
+
assert_equal true, sample_slot.key?('start_slot')
|
142
|
+
assert_equal true, sample_slot.key?('end_slot')
|
143
|
+
assert_equal true, sample_slot.key?('master')
|
144
|
+
assert_equal true, sample_slot.fetch('master').key?('ip')
|
145
|
+
assert_equal true, sample_slot.fetch('master').key?('port')
|
146
|
+
assert_equal true, sample_slot.fetch('master').key?('node_id')
|
147
|
+
assert_equal true, sample_slot.key?('replicas')
|
148
|
+
assert_equal true, sample_slot.fetch('replicas').is_a?(Array)
|
149
|
+
assert_equal true, sample_slot.fetch('replicas').first.key?('ip')
|
150
|
+
assert_equal true, sample_slot.fetch('replicas').first.key?('port')
|
151
|
+
assert_equal true, sample_slot.fetch('replicas').first.key?('node_id')
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_readonly
|
155
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'READONLY command should be...') do
|
156
|
+
redis.readonly
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_readwrite
|
161
|
+
assert_raise(Redis::Cluster::OrchestrationCommandNotSupported, 'READWRITE command should be...') do
|
162
|
+
redis.readwrite
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|