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
data/test/helper.rb DELETED
@@ -1,345 +0,0 @@
1
- require "test/unit"
2
- require "mocha/test_unit"
3
- require "logger"
4
- require "stringio"
5
-
6
- $VERBOSE = true
7
-
8
- ENV["DRIVER"] ||= "ruby"
9
-
10
- require_relative "../lib/redis"
11
- require_relative "../lib/redis/distributed"
12
- require_relative "../lib/redis/connection/#{ENV["DRIVER"]}"
13
-
14
- require_relative "support/redis_mock"
15
- require_relative "support/connection/#{ENV["DRIVER"]}"
16
- require_relative 'support/cluster/orchestrator'
17
-
18
- PORT = 6381
19
- OPTIONS = {:port => PORT, :db => 15, :timeout => Float(ENV["TIMEOUT"] || 0.1)}
20
- NODES = ["redis://127.0.0.1:#{PORT}/15"]
21
-
22
- def driver(*drivers, &blk)
23
- if drivers.map(&:to_s).include?(ENV["DRIVER"])
24
- class_eval(&blk)
25
- end
26
- end
27
-
28
- module Helper
29
-
30
- def run(runner)
31
- if respond_to?(:around)
32
- around { super(runner) }
33
- else
34
- super
35
- end
36
- end
37
-
38
- def silent
39
- verbose, $VERBOSE = $VERBOSE, false
40
-
41
- begin
42
- yield
43
- ensure
44
- $VERBOSE = verbose
45
- end
46
- end
47
-
48
- def with_external_encoding(encoding)
49
- original_encoding = Encoding.default_external
50
-
51
- begin
52
- silent { Encoding.default_external = Encoding.find(encoding) }
53
- yield
54
- ensure
55
- silent { Encoding.default_external = original_encoding }
56
- end
57
- end
58
-
59
- class Version
60
-
61
- include Comparable
62
-
63
- attr :parts
64
-
65
- def initialize(v)
66
- case v
67
- when Version
68
- @parts = v.parts
69
- else
70
- @parts = v.to_s.split(".")
71
- end
72
- end
73
-
74
- def <=>(other)
75
- other = Version.new(other)
76
- length = [self.parts.length, other.parts.length].max
77
- length.times do |i|
78
- a, b = self.parts[i], other.parts[i]
79
-
80
- return -1 if a.nil?
81
- return +1 if b.nil?
82
- return a.to_i <=> b.to_i if a != b
83
- end
84
-
85
- 0
86
- end
87
- end
88
-
89
- module Generic
90
-
91
- include Helper
92
-
93
- attr_reader :log
94
- attr_reader :redis
95
-
96
- alias :r :redis
97
-
98
- def setup
99
- @log = StringIO.new
100
- @redis = init _new_client
101
-
102
- # Run GC to make sure orphaned connections are closed.
103
- GC.start
104
- end
105
-
106
- def teardown
107
- @redis.quit if @redis
108
- end
109
-
110
- def init(redis)
111
- redis.select 14
112
- redis.flushdb
113
- redis.select 15
114
- redis.flushdb
115
- redis
116
- rescue Redis::CannotConnectError
117
- puts <<-MSG
118
-
119
- Cannot connect to Redis.
120
-
121
- Make sure Redis is running on localhost, port #{PORT}.
122
- This testing suite connects to the database 15.
123
-
124
- Try this once:
125
-
126
- $ make clean
127
-
128
- Then run the build again:
129
-
130
- $ make
131
-
132
- MSG
133
- exit 1
134
- end
135
-
136
- def redis_mock(commands, options = {}, &blk)
137
- RedisMock.start(commands, options) do |port|
138
- yield _new_client(options.merge(:port => port))
139
- end
140
- end
141
-
142
- def redis_mock_with_handler(handler, options = {}, &blk)
143
- RedisMock.start_with_handler(handler, options) do |port|
144
- yield _new_client(options.merge(:port => port))
145
- end
146
- end
147
-
148
- def assert_in_range(range, value)
149
- assert range.include?(value), "expected #{value} to be in #{range.inspect}"
150
- end
151
-
152
- def target_version(target)
153
- if version < target
154
- skip("Requires Redis > #{target}") if respond_to?(:skip)
155
- else
156
- yield
157
- end
158
- end
159
-
160
- def version
161
- Version.new(redis.info['redis_version'])
162
- end
163
- end
164
-
165
- module Client
166
-
167
- include Generic
168
-
169
- private
170
-
171
- def _format_options(options)
172
- OPTIONS.merge(:logger => ::Logger.new(@log)).merge(options)
173
- end
174
-
175
- def _new_client(options = {})
176
- Redis.new(_format_options(options).merge(:driver => ENV["DRIVER"]))
177
- end
178
- end
179
-
180
- module Distributed
181
-
182
- include Generic
183
-
184
- def version
185
- Version.new(redis.info.first["redis_version"])
186
- end
187
-
188
- private
189
-
190
- def _format_options(options)
191
- {
192
- :timeout => OPTIONS[:timeout],
193
- :logger => ::Logger.new(@log),
194
- }.merge(options)
195
- end
196
-
197
- def _new_client(options = {})
198
- Redis::Distributed.new(NODES, _format_options(options).merge(:driver => ENV["conn"]))
199
- end
200
- end
201
-
202
- module Cluster
203
- include Generic
204
-
205
- DEFAULT_HOST = '127.0.0.1'
206
- DEFAULT_PORTS = (7000..7005).freeze
207
-
208
- ClusterSlotsRawReply = lambda { |host, port|
209
- # @see https://redis.io/topics/protocol
210
- <<-REPLY.delete(' ')
211
- *1\r
212
- *4\r
213
- :0\r
214
- :16383\r
215
- *3\r
216
- $#{host.size}\r
217
- #{host}\r
218
- :#{port}\r
219
- $40\r
220
- 649fa246273043021a05f547a79478597d3f1dc5\r
221
- *3\r
222
- $#{host.size}\r
223
- #{host}\r
224
- :#{port}\r
225
- $40\r
226
- 649fa246273043021a05f547a79478597d3f1dc5\r
227
- REPLY
228
- }
229
-
230
- ClusterNodesRawReply = lambda { |host, port|
231
- line = "649fa246273043021a05f547a79478597d3f1dc5 #{host}:#{port}@17000 "\
232
- 'myself,master - 0 1530797742000 1 connected 0-16383'
233
- "$#{line.size}\r\n#{line}\r\n"
234
- }
235
-
236
- def init(redis)
237
- redis.flushall
238
- redis
239
- rescue Redis::CannotConnectError
240
- puts <<-MSG
241
-
242
- Cannot connect to Redis Cluster.
243
-
244
- Make sure Redis is running on localhost, port #{DEFAULT_PORTS}.
245
-
246
- Try this once:
247
-
248
- $ make stop_cluster
249
-
250
- Then run the build again:
251
-
252
- $ make
253
-
254
- MSG
255
- exit 1
256
- end
257
-
258
- def build_another_client(options = {})
259
- _new_client(options)
260
- end
261
-
262
- def redis_cluster_mock(commands, options = {})
263
- host = DEFAULT_HOST
264
- port = nil
265
-
266
- cluster_subcommands = if commands.key?(:cluster)
267
- commands.delete(:cluster)
268
- .map { |k, v| [k.to_s.downcase, v] }
269
- .to_h
270
- else
271
- {}
272
- end
273
-
274
- commands[:cluster] = lambda { |subcommand, *args|
275
- if cluster_subcommands.key?(subcommand)
276
- cluster_subcommands[subcommand].call(*args)
277
- else
278
- case subcommand
279
- when 'slots' then ClusterSlotsRawReply.call(host, port)
280
- when 'nodes' then ClusterNodesRawReply.call(host, port)
281
- else '+OK'
282
- end
283
- end
284
- }
285
-
286
- commands[:command] = ->(*_) { "*0\r\n" }
287
-
288
- RedisMock.start(commands, options) do |po|
289
- port = po
290
- scheme = options[:ssl] ? 'rediss' : 'redis'
291
- nodes = %W[#{scheme}://#{host}:#{port}]
292
- yield _new_client(options.merge(cluster: nodes))
293
- end
294
- end
295
-
296
- def redis_cluster_down
297
- trib = ClusterOrchestrator.new(_default_nodes)
298
- trib.down
299
- yield
300
- ensure
301
- trib.rebuild
302
- trib.close
303
- end
304
-
305
- def redis_cluster_failover
306
- trib = ClusterOrchestrator.new(_default_nodes)
307
- trib.failover
308
- yield
309
- ensure
310
- trib.rebuild
311
- trib.close
312
- end
313
-
314
- # @param slot [Integer]
315
- # @param src [String] <ip>:<port>
316
- # @param dest [String] <ip>:<port>
317
- def redis_cluster_resharding(slot, src:, dest:)
318
- trib = ClusterOrchestrator.new(_default_nodes)
319
- trib.start_resharding(slot, src, dest)
320
- yield
321
- trib.finish_resharding(slot, dest)
322
- ensure
323
- trib.rebuild
324
- trib.close
325
- end
326
-
327
- private
328
-
329
- def _default_nodes(host: DEFAULT_HOST, ports: DEFAULT_PORTS)
330
- ports.map { |port| "redis://#{host}:#{port}" }
331
- end
332
-
333
- def _format_options(options)
334
- {
335
- timeout: OPTIONS[:timeout],
336
- logger: ::Logger.new(@log),
337
- cluster: _default_nodes
338
- }.merge(options)
339
- end
340
-
341
- def _new_client(options = {})
342
- Redis.new(_format_options(options).merge(driver: ENV['DRIVER']))
343
- end
344
- end
345
- end
data/test/helper_test.rb DELETED
@@ -1,22 +0,0 @@
1
- require_relative "helper"
2
-
3
- class TestHelper < Test::Unit::TestCase
4
-
5
- include Helper
6
-
7
- def test_version_comparison
8
- v = Version.new("2.0.1")
9
-
10
- assert v > "1"
11
- assert v > "2"
12
- assert v < "3"
13
- assert v < "10"
14
-
15
- assert v < "2.1"
16
- assert v < "2.0.2"
17
- assert v < "2.0.1.1"
18
- assert v < "2.0.10"
19
-
20
- assert v == "2.0.1"
21
- end
22
- end