redis 4.0.3 → 4.5.0

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 (157) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +110 -0
  3. data/README.md +126 -17
  4. data/lib/redis/client.rb +130 -82
  5. data/lib/redis/cluster/command_loader.rb +8 -7
  6. data/lib/redis/cluster/node.rb +5 -1
  7. data/lib/redis/cluster/node_key.rb +3 -7
  8. data/lib/redis/cluster/node_loader.rb +2 -0
  9. data/lib/redis/cluster/option.rb +31 -14
  10. data/lib/redis/cluster/slot.rb +30 -13
  11. data/lib/redis/cluster/slot_loader.rb +6 -4
  12. data/lib/redis/cluster.rb +23 -17
  13. data/lib/redis/connection/command_helper.rb +5 -2
  14. data/lib/redis/connection/hiredis.rb +4 -3
  15. data/lib/redis/connection/registry.rb +2 -1
  16. data/lib/redis/connection/ruby.rb +139 -106
  17. data/lib/redis/connection/synchrony.rb +9 -4
  18. data/lib/redis/connection.rb +2 -0
  19. data/lib/redis/distributed.rb +171 -70
  20. data/lib/redis/errors.rb +2 -0
  21. data/lib/redis/hash_ring.rb +15 -14
  22. data/lib/redis/pipeline.rb +46 -8
  23. data/lib/redis/subscribe.rb +11 -12
  24. data/lib/redis/version.rb +3 -1
  25. data/lib/redis.rb +1239 -426
  26. metadata +16 -262
  27. data/.gitignore +0 -19
  28. data/.travis/Gemfile +0 -18
  29. data/.travis.yml +0 -61
  30. data/.yardopts +0 -3
  31. data/Gemfile +0 -8
  32. data/benchmarking/logging.rb +0 -71
  33. data/benchmarking/pipeline.rb +0 -51
  34. data/benchmarking/speed.rb +0 -21
  35. data/benchmarking/suite.rb +0 -24
  36. data/benchmarking/worker.rb +0 -71
  37. data/bin/build +0 -71
  38. data/bors.toml +0 -14
  39. data/examples/basic.rb +0 -15
  40. data/examples/consistency.rb +0 -114
  41. data/examples/dist_redis.rb +0 -43
  42. data/examples/incr-decr.rb +0 -17
  43. data/examples/list.rb +0 -26
  44. data/examples/pubsub.rb +0 -37
  45. data/examples/sentinel/sentinel.conf +0 -9
  46. data/examples/sentinel/start +0 -49
  47. data/examples/sentinel.rb +0 -41
  48. data/examples/sets.rb +0 -36
  49. data/examples/unicorn/config.ru +0 -3
  50. data/examples/unicorn/unicorn.rb +0 -20
  51. data/makefile +0 -74
  52. data/redis.gemspec +0 -43
  53. data/test/bitpos_test.rb +0 -63
  54. data/test/blocking_commands_test.rb +0 -40
  55. data/test/client_test.rb +0 -76
  56. data/test/cluster_abnormal_state_test.rb +0 -38
  57. data/test/cluster_blocking_commands_test.rb +0 -15
  58. data/test/cluster_client_internals_test.rb +0 -77
  59. data/test/cluster_client_key_hash_tags_test.rb +0 -88
  60. data/test/cluster_client_options_test.rb +0 -147
  61. data/test/cluster_client_pipelining_test.rb +0 -59
  62. data/test/cluster_client_replicas_test.rb +0 -36
  63. data/test/cluster_client_slots_test.rb +0 -94
  64. data/test/cluster_client_transactions_test.rb +0 -71
  65. data/test/cluster_commands_on_cluster_test.rb +0 -165
  66. data/test/cluster_commands_on_connection_test.rb +0 -40
  67. data/test/cluster_commands_on_geo_test.rb +0 -74
  68. data/test/cluster_commands_on_hashes_test.rb +0 -11
  69. data/test/cluster_commands_on_hyper_log_log_test.rb +0 -17
  70. data/test/cluster_commands_on_keys_test.rb +0 -134
  71. data/test/cluster_commands_on_lists_test.rb +0 -15
  72. data/test/cluster_commands_on_pub_sub_test.rb +0 -101
  73. data/test/cluster_commands_on_scripting_test.rb +0 -56
  74. data/test/cluster_commands_on_server_test.rb +0 -221
  75. data/test/cluster_commands_on_sets_test.rb +0 -39
  76. data/test/cluster_commands_on_sorted_sets_test.rb +0 -35
  77. data/test/cluster_commands_on_streams_test.rb +0 -196
  78. data/test/cluster_commands_on_strings_test.rb +0 -15
  79. data/test/cluster_commands_on_transactions_test.rb +0 -41
  80. data/test/cluster_commands_on_value_types_test.rb +0 -14
  81. data/test/command_map_test.rb +0 -28
  82. data/test/commands_on_geo_test.rb +0 -116
  83. data/test/commands_on_hashes_test.rb +0 -7
  84. data/test/commands_on_hyper_log_log_test.rb +0 -7
  85. data/test/commands_on_lists_test.rb +0 -7
  86. data/test/commands_on_sets_test.rb +0 -7
  87. data/test/commands_on_sorted_sets_test.rb +0 -7
  88. data/test/commands_on_strings_test.rb +0 -7
  89. data/test/commands_on_value_types_test.rb +0 -207
  90. data/test/connection_handling_test.rb +0 -275
  91. data/test/connection_test.rb +0 -57
  92. data/test/db/.gitkeep +0 -0
  93. data/test/distributed_blocking_commands_test.rb +0 -52
  94. data/test/distributed_commands_on_hashes_test.rb +0 -21
  95. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -26
  96. data/test/distributed_commands_on_lists_test.rb +0 -19
  97. data/test/distributed_commands_on_sets_test.rb +0 -105
  98. data/test/distributed_commands_on_sorted_sets_test.rb +0 -59
  99. data/test/distributed_commands_on_strings_test.rb +0 -79
  100. data/test/distributed_commands_on_value_types_test.rb +0 -129
  101. data/test/distributed_commands_requiring_clustering_test.rb +0 -162
  102. data/test/distributed_connection_handling_test.rb +0 -21
  103. data/test/distributed_internals_test.rb +0 -68
  104. data/test/distributed_key_tags_test.rb +0 -50
  105. data/test/distributed_persistence_control_commands_test.rb +0 -24
  106. data/test/distributed_publish_subscribe_test.rb +0 -90
  107. data/test/distributed_remote_server_control_commands_test.rb +0 -64
  108. data/test/distributed_scripting_test.rb +0 -100
  109. data/test/distributed_sorting_test.rb +0 -18
  110. data/test/distributed_test.rb +0 -56
  111. data/test/distributed_transactions_test.rb +0 -30
  112. data/test/encoding_test.rb +0 -14
  113. data/test/error_replies_test.rb +0 -57
  114. data/test/fork_safety_test.rb +0 -60
  115. data/test/helper.rb +0 -345
  116. data/test/helper_test.rb +0 -22
  117. data/test/internals_test.rb +0 -408
  118. data/test/lint/blocking_commands.rb +0 -174
  119. data/test/lint/hashes.rb +0 -203
  120. data/test/lint/hyper_log_log.rb +0 -74
  121. data/test/lint/lists.rb +0 -159
  122. data/test/lint/sets.rb +0 -282
  123. data/test/lint/sorted_sets.rb +0 -497
  124. data/test/lint/strings.rb +0 -348
  125. data/test/lint/value_types.rb +0 -130
  126. data/test/persistence_control_commands_test.rb +0 -24
  127. data/test/pipelining_commands_test.rb +0 -246
  128. data/test/publish_subscribe_test.rb +0 -280
  129. data/test/remote_server_control_commands_test.rb +0 -175
  130. data/test/scanning_test.rb +0 -407
  131. data/test/scripting_test.rb +0 -76
  132. data/test/sentinel_command_test.rb +0 -78
  133. data/test/sentinel_test.rb +0 -253
  134. data/test/sorting_test.rb +0 -57
  135. data/test/ssl_test.rb +0 -69
  136. data/test/support/cluster/orchestrator.rb +0 -199
  137. data/test/support/connection/hiredis.rb +0 -1
  138. data/test/support/connection/ruby.rb +0 -1
  139. data/test/support/connection/synchrony.rb +0 -17
  140. data/test/support/redis_mock.rb +0 -130
  141. data/test/support/ssl/gen_certs.sh +0 -31
  142. data/test/support/ssl/trusted-ca.crt +0 -25
  143. data/test/support/ssl/trusted-ca.key +0 -27
  144. data/test/support/ssl/trusted-cert.crt +0 -81
  145. data/test/support/ssl/trusted-cert.key +0 -28
  146. data/test/support/ssl/untrusted-ca.crt +0 -26
  147. data/test/support/ssl/untrusted-ca.key +0 -27
  148. data/test/support/ssl/untrusted-cert.crt +0 -82
  149. data/test/support/ssl/untrusted-cert.key +0 -28
  150. data/test/support/wire/synchrony.rb +0 -24
  151. data/test/support/wire/thread.rb +0 -5
  152. data/test/synchrony_driver.rb +0 -85
  153. data/test/test.conf.erb +0 -9
  154. data/test/thread_safety_test.rb +0 -60
  155. data/test/transactions_test.rb +0 -272
  156. data/test/unknown_commands_test.rb +0 -12
  157. data/test/url_param_test.rb +0 -136
@@ -1,253 +0,0 @@
1
- require_relative "helper"
2
-
3
- class SentinelTest < Test::Unit::TestCase
4
-
5
- include Helper::Client
6
-
7
- def test_sentinel_connection
8
- sentinels = [{:host => "127.0.0.1", :port => 26381},
9
- {:host => "127.0.0.1", :port => 26382}]
10
-
11
- commands = {
12
- :s1 => [],
13
- :s2 => [],
14
- }
15
-
16
- handler = lambda do |id|
17
- {
18
- :sentinel => lambda do |command, *args|
19
- commands[id] << [command, *args]
20
- ["127.0.0.1", "6381"]
21
- end
22
- }
23
- end
24
-
25
- RedisMock.start(handler.call(:s1)) do |s1_port|
26
- RedisMock.start(handler.call(:s2)) do |s2_port|
27
- sentinels[0][:port] = s1_port
28
- sentinels[1][:port] = s2_port
29
- redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master)
30
-
31
- assert redis.ping
32
- end
33
- end
34
-
35
- assert_equal commands[:s1], [%w[get-master-addr-by-name master1]]
36
- assert_equal commands[:s2], []
37
- end
38
-
39
- def test_sentinel_failover
40
- sentinels = [{:host => "127.0.0.1", :port => 26381},
41
- {:host => "127.0.0.1", :port => 26382}]
42
-
43
- commands = {
44
- :s1 => [],
45
- :s2 => [],
46
- }
47
-
48
- s1 = {
49
- :sentinel => lambda do |command, *args|
50
- commands[:s1] << [command, *args]
51
- "$-1" # Nil
52
- end
53
- }
54
-
55
- s2 = {
56
- :sentinel => lambda do |command, *args|
57
- commands[:s2] << [command, *args]
58
- ["127.0.0.1", "6381"]
59
- end
60
- }
61
-
62
- RedisMock.start(s1) do |s1_port|
63
- RedisMock.start(s2) do |s2_port|
64
- sentinels[0][:port] = s1_port
65
- sentinels[1][:port] = s2_port
66
- redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master)
67
-
68
- assert redis.ping
69
- end
70
- end
71
-
72
- assert_equal commands[:s1], [%w[get-master-addr-by-name master1]]
73
- assert_equal commands[:s2], [%w[get-master-addr-by-name master1]]
74
- end
75
-
76
- def test_sentinel_failover_prioritize_healthy_sentinel
77
- sentinels = [{:host => "127.0.0.1", :port => 26381},
78
- {:host => "127.0.0.1", :port => 26382}]
79
-
80
- commands = {
81
- :s1 => [],
82
- :s2 => [],
83
- }
84
-
85
- s1 = {
86
- :sentinel => lambda do |command, *args|
87
- commands[:s1] << [command, *args]
88
- "$-1" # Nil
89
- end
90
- }
91
-
92
- s2 = {
93
- :sentinel => lambda do |command, *args|
94
- commands[:s2] << [command, *args]
95
- ["127.0.0.1", "6381"]
96
- end
97
- }
98
-
99
- RedisMock.start(s1) do |s1_port|
100
- RedisMock.start(s2) do |s2_port|
101
- sentinels[0][:port] = s1_port
102
- sentinels[1][:port] = s2_port
103
- redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master)
104
-
105
- assert redis.ping
106
-
107
- redis.quit
108
-
109
- assert redis.ping
110
- end
111
- end
112
-
113
- assert_equal commands[:s1], [%w[get-master-addr-by-name master1]]
114
- assert_equal commands[:s2], [%w[get-master-addr-by-name master1], %w[get-master-addr-by-name master1]]
115
- end
116
-
117
- def test_sentinel_with_non_sentinel_options
118
- sentinels = [{:host => "127.0.0.1", :port => 26381}]
119
-
120
- commands = {
121
- :s1 => [],
122
- :m1 => []
123
- }
124
-
125
- sentinel = lambda do |port|
126
- {
127
- :auth => lambda do |pass|
128
- commands[:s1] << ["auth", pass]
129
- "-ERR unknown command 'auth'"
130
- end,
131
- :select => lambda do |db|
132
- commands[:s1] << ["select", db]
133
- "-ERR unknown command 'select'"
134
- end,
135
- :sentinel => lambda do |command, *args|
136
- commands[:s1] << [command, *args]
137
- ["127.0.0.1", port.to_s]
138
- end
139
- }
140
- end
141
-
142
- master = {
143
- :auth => lambda do |pass|
144
- commands[:m1] << ["auth", pass]
145
- "+OK"
146
- end,
147
- :role => lambda do
148
- commands[:m1] << ["role"]
149
- ["master"]
150
- end
151
- }
152
-
153
- RedisMock.start(master) do |master_port|
154
- RedisMock.start(sentinel.call(master_port)) do |sen_port|
155
- sentinels[0][:port] = sen_port
156
- redis = Redis.new(:url => "redis://:foo@master1/15", :sentinels => sentinels, :role => :master)
157
-
158
- assert redis.ping
159
- end
160
- end
161
-
162
- assert_equal [%w[get-master-addr-by-name master1]], commands[:s1]
163
- assert_equal [%w[auth foo], %w[role]], commands[:m1]
164
- end
165
-
166
- def test_sentinel_role_mismatch
167
- sentinels = [{:host => "127.0.0.1", :port => 26381}]
168
-
169
- sentinel = lambda do |port|
170
- {
171
- :sentinel => lambda do |command, *args|
172
- ["127.0.0.1", port.to_s]
173
- end
174
- }
175
- end
176
-
177
- master = {
178
- :role => lambda do
179
- ["slave"]
180
- end
181
- }
182
-
183
- ex = assert_raise(Redis::ConnectionError) do
184
- RedisMock.start(master) do |master_port|
185
- RedisMock.start(sentinel.call(master_port)) do |sen_port|
186
- sentinels[0][:port] = sen_port
187
- redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master)
188
-
189
- assert redis.ping
190
- end
191
- end
192
- end
193
-
194
- assert_match(/Instance role mismatch/, ex.message)
195
- end
196
-
197
- def test_sentinel_retries
198
- sentinels = [{:host => "127.0.0.1", :port => 26381},
199
- {:host => "127.0.0.1", :port => 26382}]
200
-
201
- connections = []
202
-
203
- handler = lambda do |id, port|
204
- {
205
- :sentinel => lambda do |command, *args|
206
- connections << id
207
-
208
- if connections.count(id) < 2
209
- :close
210
- else
211
- ["127.0.0.1", port.to_s]
212
- end
213
- end
214
- }
215
- end
216
-
217
- master = {
218
- :role => lambda do
219
- ["master"]
220
- end
221
- }
222
-
223
- RedisMock.start(master) do |master_port|
224
- RedisMock.start(handler.call(:s1, master_port)) do |s1_port|
225
- RedisMock.start(handler.call(:s2, master_port)) do |s2_port|
226
- sentinels[0][:port] = s1_port
227
- sentinels[1][:port] = s2_port
228
- redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master, :reconnect_attempts => 1)
229
-
230
- assert redis.ping
231
- end
232
- end
233
- end
234
-
235
- assert_equal [:s1, :s2, :s1], connections
236
-
237
- connections.clear
238
-
239
- ex = assert_raise(Redis::CannotConnectError) do
240
- RedisMock.start(master) do |master_port|
241
- RedisMock.start(handler.call(:s1, master_port)) do |s1_port|
242
- RedisMock.start(handler.call(:s2, master_port)) do |s2_port|
243
- redis = Redis.new(:url => "redis://master1", :sentinels => sentinels, :role => :master, :reconnect_attempts => 0)
244
-
245
- assert redis.ping
246
- end
247
- end
248
- end
249
- end
250
-
251
- assert_match(/No sentinels available/, ex.message)
252
- end
253
- end
data/test/sorting_test.rb DELETED
@@ -1,57 +0,0 @@
1
- require_relative "helper"
2
-
3
- class TestSorting < Test::Unit::TestCase
4
-
5
- include Helper::Client
6
-
7
- def test_sort
8
- r.set("foo:1", "s1")
9
- r.set("foo:2", "s2")
10
-
11
- r.rpush("bar", "1")
12
- r.rpush("bar", "2")
13
-
14
- assert_equal ["s1"], r.sort("bar", :get => "foo:*", :limit => [0, 1])
15
- assert_equal ["s2"], r.sort("bar", :get => "foo:*", :limit => [0, 1], :order => "desc alpha")
16
- end
17
-
18
- def test_sort_with_an_array_of_gets
19
- r.set("foo:1:a", "s1a")
20
- r.set("foo:1:b", "s1b")
21
-
22
- r.set("foo:2:a", "s2a")
23
- r.set("foo:2:b", "s2b")
24
-
25
- r.rpush("bar", "1")
26
- r.rpush("bar", "2")
27
-
28
- assert_equal [["s1a", "s1b"]], r.sort("bar", :get => ["foo:*:a", "foo:*:b"], :limit => [0, 1])
29
- assert_equal [["s2a", "s2b"]], r.sort("bar", :get => ["foo:*:a", "foo:*:b"], :limit => [0, 1], :order => "desc alpha")
30
- assert_equal [["s1a", "s1b"], ["s2a", "s2b"]], r.sort("bar", :get => ["foo:*:a", "foo:*:b"])
31
- end
32
-
33
- def test_sort_with_store
34
- r.set("foo:1", "s1")
35
- r.set("foo:2", "s2")
36
-
37
- r.rpush("bar", "1")
38
- r.rpush("bar", "2")
39
-
40
- r.sort("bar", :get => "foo:*", :store => "baz")
41
- assert_equal ["s1", "s2"], r.lrange("baz", 0, -1)
42
- end
43
-
44
- def test_sort_with_an_array_of_gets_and_with_store
45
- r.set("foo:1:a", "s1a")
46
- r.set("foo:1:b", "s1b")
47
-
48
- r.set("foo:2:a", "s2a")
49
- r.set("foo:2:b", "s2b")
50
-
51
- r.rpush("bar", "1")
52
- r.rpush("bar", "2")
53
-
54
- r.sort("bar", :get => ["foo:*:a", "foo:*:b"], :store => 'baz')
55
- assert_equal ["s1a", "s1b", "s2a", "s2b"], r.lrange("baz", 0, -1)
56
- end
57
- end
data/test/ssl_test.rb DELETED
@@ -1,69 +0,0 @@
1
- require_relative "helper"
2
-
3
- class SslTest < Test::Unit::TestCase
4
-
5
- include Helper::Client
6
-
7
- driver(:ruby) do
8
-
9
- def test_verified_ssl_connection
10
- RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("trusted")) do |port|
11
- redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file })
12
- assert_equal redis.ping, "PONG"
13
- end
14
- end
15
-
16
- def test_unverified_ssl_connection
17
- assert_raise(OpenSSL::SSL::SSLError) do
18
- RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("untrusted")) do |port|
19
- redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file })
20
- redis.ping
21
- end
22
- end
23
- end
24
-
25
- def test_ssl_blocking
26
- RedisMock.start({}, ssl_server_opts("trusted")) do |port|
27
- redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file })
28
- assert_equal redis.set("boom", "a" * 10_000_000), "OK"
29
- end
30
- end
31
-
32
- end
33
-
34
- driver(:hiredis, :synchrony) do
35
-
36
- def test_ssl_not_implemented_exception
37
- assert_raise(NotImplementedError) do
38
- RedisMock.start({ :ping => proc { "+PONG" } }, ssl_server_opts("trusted")) do |port|
39
- redis = Redis.new(:port => port, :ssl => true, :ssl_params => { :ca_file => ssl_ca_file })
40
- redis.ping
41
- end
42
- end
43
- end
44
-
45
- end
46
-
47
- private
48
-
49
- def ssl_server_opts(prefix)
50
- ssl_cert = File.join(cert_path, "#{prefix}-cert.crt")
51
- ssl_key = File.join(cert_path, "#{prefix}-cert.key")
52
-
53
- {
54
- :ssl => true,
55
- :ssl_params => {
56
- :cert => OpenSSL::X509::Certificate.new(File.read(ssl_cert)),
57
- :key => OpenSSL::PKey::RSA.new(File.read(ssl_key))
58
- }
59
- }
60
- end
61
-
62
- def ssl_ca_file
63
- File.join(cert_path, "trusted-ca.crt")
64
- end
65
-
66
- def cert_path
67
- File.expand_path("../support/ssl/", __FILE__)
68
- end
69
- end
@@ -1,199 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../../../lib/redis'
4
-
5
- class ClusterOrchestrator
6
- SLOT_SIZE = 16384
7
-
8
- def initialize(node_addrs)
9
- raise 'Redis Cluster requires at least 3 master nodes.' if node_addrs.size < 3
10
- @clients = node_addrs.map { |addr| Redis.new(url: addr) }
11
- end
12
-
13
- def rebuild
14
- flush_all_data(@clients)
15
- reset_cluster(@clients)
16
- assign_slots(@clients)
17
- save_config_epoch(@clients)
18
- meet_each_other(@clients)
19
- wait_meeting(@clients)
20
- replicate(@clients)
21
- save_config(@clients)
22
- wait_cluster_building(@clients)
23
- sleep 3
24
- end
25
-
26
- def down
27
- flush_all_data(@clients)
28
- reset_cluster(@clients)
29
- end
30
-
31
- def failover
32
- take_slaves(@clients).last.cluster(:failover, :takeover)
33
- sleep 3
34
- end
35
-
36
- def start_resharding(slot, src_node_key, dest_node_key)
37
- node_map = hashify_node_map(@clients.first)
38
- src_node_id = node_map.fetch(src_node_key)
39
- src_client = find_client(@clients, src_node_key)
40
- dest_node_id = node_map.fetch(dest_node_key)
41
- dest_client = find_client(@clients, dest_node_key)
42
- dest_host, dest_port = dest_node_key.split(':')
43
-
44
- dest_client.cluster(:setslot, slot, 'IMPORTING', src_node_id)
45
- src_client.cluster(:setslot, slot, 'MIGRATING', dest_node_id)
46
-
47
- loop do
48
- keys = src_client.cluster(:getkeysinslot, slot, 100)
49
- break if keys.empty?
50
- keys.each { |k| src_client.migrate(k, host: dest_host, port: dest_port) }
51
- sleep 0.1
52
- end
53
- end
54
-
55
- def finish_resharding(slot, dest_node_key)
56
- node_map = hashify_node_map(@clients.first)
57
- @clients.first.cluster(:setslot, slot, 'NODE', node_map.fetch(dest_node_key))
58
- end
59
-
60
- def close
61
- @clients.each(&:quit)
62
- end
63
-
64
- private
65
-
66
- def flush_all_data(clients)
67
- clients.each do |c|
68
- begin
69
- c.flushall
70
- rescue Redis::CommandError
71
- # READONLY You can't write against a read only slave.
72
- nil
73
- end
74
- end
75
- end
76
-
77
- def reset_cluster(clients)
78
- clients.each { |c| c.cluster(:reset) }
79
- end
80
-
81
- def assign_slots(clients)
82
- masters = take_masters(clients)
83
- slot_slice = SLOT_SIZE / masters.size
84
- mod = SLOT_SIZE % masters.size
85
- slot_sizes = Array.new(masters.size, slot_slice)
86
- mod.downto(1) { |i| slot_sizes[i] += 1 }
87
-
88
- slot_idx = 0
89
- masters.zip(slot_sizes).each do |c, s|
90
- slot_range = slot_idx..slot_idx + s - 1
91
- c.cluster(:addslots, *slot_range.to_a)
92
- slot_idx += s
93
- end
94
- end
95
-
96
- def save_config_epoch(clients)
97
- clients.each_with_index do |c, i|
98
- begin
99
- c.cluster('set-config-epoch', i + 1)
100
- rescue Redis::CommandError
101
- # ERR Node config epoch is already non-zero
102
- nil
103
- end
104
- end
105
- end
106
-
107
- def meet_each_other(clients)
108
- first_cliient = clients.first
109
- target_info = first_cliient.connection
110
- target_host = target_info.fetch(:host)
111
- target_port = target_info.fetch(:port)
112
-
113
- clients.each do |client|
114
- next if first_cliient.id == client.id
115
- client.cluster(:meet, target_host, target_port)
116
- end
117
- end
118
-
119
- def wait_meeting(clients)
120
- first_cliient = clients.first
121
- size = clients.size
122
-
123
- loop do
124
- info = hashify_cluster_info(first_cliient)
125
- break if info['cluster_known_nodes'].to_i == size
126
- sleep 0.1
127
- end
128
- end
129
-
130
- def replicate(clients)
131
- node_map = hashify_node_map(clients.first)
132
- masters = take_masters(clients)
133
-
134
- take_slaves(clients).each_with_index do |slave, i|
135
- master_info = masters[i].connection
136
- master_host = master_info.fetch(:host)
137
- master_port = master_info.fetch(:port)
138
-
139
- loop do
140
- begin
141
- master_node_id = node_map.fetch("#{master_host}:#{master_port}")
142
- slave.cluster(:replicate, master_node_id)
143
- rescue Redis::CommandError
144
- # ERR Unknown node [key]
145
- sleep 0.1
146
- node_map = hashify_node_map(clients.first)
147
- next
148
- end
149
-
150
- break
151
- end
152
- end
153
- end
154
-
155
- def save_config(clients)
156
- clients.each { |c| c.cluster(:saveconfig) }
157
- end
158
-
159
- def wait_cluster_building(clients)
160
- first_cliient = clients.first
161
-
162
- loop do
163
- info = hashify_cluster_info(first_cliient)
164
- break if info['cluster_state'] == 'ok'
165
- sleep 0.1
166
- end
167
- end
168
-
169
- def hashify_cluster_info(client)
170
- client.cluster(:info).split("\r\n").map { |str| str.split(':') }.to_h
171
- end
172
-
173
- def hashify_node_map(client)
174
- client.cluster(:nodes)
175
- .split("\n")
176
- .map { |str| str.split(' ') }
177
- .map { |arr| [arr[1].split('@').first, arr[0]] }
178
- .to_h
179
- end
180
-
181
- def take_masters(clients)
182
- size = clients.size / 2
183
- return clients if size < 3
184
- clients.take(size)
185
- end
186
-
187
- def take_slaves(clients)
188
- size = clients.size / 2
189
- return [] if size < 3
190
- clients[size..size * 2]
191
- end
192
-
193
- def find_client(clients, node_key)
194
- clients.find do |cli|
195
- con = cli.connection
196
- node_key == "#{con.fetch(:host)}:#{con.fetch(:port)}"
197
- end
198
- end
199
- end
@@ -1 +0,0 @@
1
- require_relative "../wire/thread"
@@ -1 +0,0 @@
1
- require_relative "../wire/thread"
@@ -1,17 +0,0 @@
1
- require_relative "../wire/synchrony"
2
-
3
- module Helper
4
- def around
5
- rv = nil
6
-
7
- EM.synchrony do
8
- begin
9
- rv = yield
10
- ensure
11
- EM.stop
12
- end
13
- end
14
-
15
- rv
16
- end
17
- end