redis 4.0.1 → 4.8.1

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 (148) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +220 -0
  3. data/README.md +152 -28
  4. data/lib/redis/client.rb +171 -107
  5. data/lib/redis/cluster/command.rb +79 -0
  6. data/lib/redis/cluster/command_loader.rb +33 -0
  7. data/lib/redis/cluster/key_slot_converter.rb +72 -0
  8. data/lib/redis/cluster/node.rb +120 -0
  9. data/lib/redis/cluster/node_key.rb +31 -0
  10. data/lib/redis/cluster/node_loader.rb +34 -0
  11. data/lib/redis/cluster/option.rb +100 -0
  12. data/lib/redis/cluster/slot.rb +86 -0
  13. data/lib/redis/cluster/slot_loader.rb +46 -0
  14. data/lib/redis/cluster.rb +315 -0
  15. data/lib/redis/commands/bitmaps.rb +63 -0
  16. data/lib/redis/commands/cluster.rb +45 -0
  17. data/lib/redis/commands/connection.rb +58 -0
  18. data/lib/redis/commands/geo.rb +84 -0
  19. data/lib/redis/commands/hashes.rb +251 -0
  20. data/lib/redis/commands/hyper_log_log.rb +37 -0
  21. data/lib/redis/commands/keys.rb +455 -0
  22. data/lib/redis/commands/lists.rb +290 -0
  23. data/lib/redis/commands/pubsub.rb +72 -0
  24. data/lib/redis/commands/scripting.rb +114 -0
  25. data/lib/redis/commands/server.rb +188 -0
  26. data/lib/redis/commands/sets.rb +223 -0
  27. data/lib/redis/commands/sorted_sets.rb +812 -0
  28. data/lib/redis/commands/streams.rb +382 -0
  29. data/lib/redis/commands/strings.rb +313 -0
  30. data/lib/redis/commands/transactions.rb +139 -0
  31. data/lib/redis/commands.rb +240 -0
  32. data/lib/redis/connection/command_helper.rb +5 -2
  33. data/lib/redis/connection/hiredis.rb +7 -5
  34. data/lib/redis/connection/registry.rb +2 -1
  35. data/lib/redis/connection/ruby.rb +139 -111
  36. data/lib/redis/connection/synchrony.rb +17 -10
  37. data/lib/redis/connection.rb +3 -1
  38. data/lib/redis/distributed.rb +244 -87
  39. data/lib/redis/errors.rb +57 -0
  40. data/lib/redis/hash_ring.rb +15 -14
  41. data/lib/redis/pipeline.rb +181 -10
  42. data/lib/redis/subscribe.rb +11 -12
  43. data/lib/redis/version.rb +3 -1
  44. data/lib/redis.rb +180 -2716
  45. metadata +45 -195
  46. data/.gitignore +0 -16
  47. data/.travis/Gemfile +0 -13
  48. data/.travis.yml +0 -73
  49. data/.yardopts +0 -3
  50. data/Gemfile +0 -3
  51. data/benchmarking/logging.rb +0 -71
  52. data/benchmarking/pipeline.rb +0 -51
  53. data/benchmarking/speed.rb +0 -21
  54. data/benchmarking/suite.rb +0 -24
  55. data/benchmarking/worker.rb +0 -71
  56. data/bors.toml +0 -14
  57. data/examples/basic.rb +0 -15
  58. data/examples/consistency.rb +0 -114
  59. data/examples/dist_redis.rb +0 -43
  60. data/examples/incr-decr.rb +0 -17
  61. data/examples/list.rb +0 -26
  62. data/examples/pubsub.rb +0 -37
  63. data/examples/sentinel/sentinel.conf +0 -9
  64. data/examples/sentinel/start +0 -49
  65. data/examples/sentinel.rb +0 -41
  66. data/examples/sets.rb +0 -36
  67. data/examples/unicorn/config.ru +0 -3
  68. data/examples/unicorn/unicorn.rb +0 -20
  69. data/makefile +0 -42
  70. data/redis.gemspec +0 -42
  71. data/test/bitpos_test.rb +0 -63
  72. data/test/blocking_commands_test.rb +0 -40
  73. data/test/client_test.rb +0 -59
  74. data/test/command_map_test.rb +0 -28
  75. data/test/commands_on_hashes_test.rb +0 -19
  76. data/test/commands_on_hyper_log_log_test.rb +0 -19
  77. data/test/commands_on_lists_test.rb +0 -18
  78. data/test/commands_on_sets_test.rb +0 -75
  79. data/test/commands_on_sorted_sets_test.rb +0 -150
  80. data/test/commands_on_strings_test.rb +0 -99
  81. data/test/commands_on_value_types_test.rb +0 -171
  82. data/test/connection_handling_test.rb +0 -275
  83. data/test/connection_test.rb +0 -57
  84. data/test/db/.gitkeep +0 -0
  85. data/test/distributed_blocking_commands_test.rb +0 -44
  86. data/test/distributed_commands_on_hashes_test.rb +0 -8
  87. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -31
  88. data/test/distributed_commands_on_lists_test.rb +0 -20
  89. data/test/distributed_commands_on_sets_test.rb +0 -106
  90. data/test/distributed_commands_on_sorted_sets_test.rb +0 -16
  91. data/test/distributed_commands_on_strings_test.rb +0 -69
  92. data/test/distributed_commands_on_value_types_test.rb +0 -93
  93. data/test/distributed_commands_requiring_clustering_test.rb +0 -162
  94. data/test/distributed_connection_handling_test.rb +0 -21
  95. data/test/distributed_internals_test.rb +0 -68
  96. data/test/distributed_key_tags_test.rb +0 -50
  97. data/test/distributed_persistence_control_commands_test.rb +0 -24
  98. data/test/distributed_publish_subscribe_test.rb +0 -90
  99. data/test/distributed_remote_server_control_commands_test.rb +0 -64
  100. data/test/distributed_scripting_test.rb +0 -100
  101. data/test/distributed_sorting_test.rb +0 -18
  102. data/test/distributed_test.rb +0 -56
  103. data/test/distributed_transactions_test.rb +0 -30
  104. data/test/encoding_test.rb +0 -14
  105. data/test/error_replies_test.rb +0 -57
  106. data/test/fork_safety_test.rb +0 -60
  107. data/test/helper.rb +0 -201
  108. data/test/helper_test.rb +0 -22
  109. data/test/internals_test.rb +0 -389
  110. data/test/lint/blocking_commands.rb +0 -150
  111. data/test/lint/hashes.rb +0 -162
  112. data/test/lint/hyper_log_log.rb +0 -60
  113. data/test/lint/lists.rb +0 -143
  114. data/test/lint/sets.rb +0 -140
  115. data/test/lint/sorted_sets.rb +0 -316
  116. data/test/lint/strings.rb +0 -246
  117. data/test/lint/value_types.rb +0 -130
  118. data/test/persistence_control_commands_test.rb +0 -24
  119. data/test/pipelining_commands_test.rb +0 -238
  120. data/test/publish_subscribe_test.rb +0 -280
  121. data/test/remote_server_control_commands_test.rb +0 -175
  122. data/test/scanning_test.rb +0 -407
  123. data/test/scripting_test.rb +0 -76
  124. data/test/sentinel_command_test.rb +0 -78
  125. data/test/sentinel_test.rb +0 -253
  126. data/test/sorting_test.rb +0 -57
  127. data/test/ssl_test.rb +0 -69
  128. data/test/support/connection/hiredis.rb +0 -1
  129. data/test/support/connection/ruby.rb +0 -1
  130. data/test/support/connection/synchrony.rb +0 -17
  131. data/test/support/redis_mock.rb +0 -130
  132. data/test/support/ssl/gen_certs.sh +0 -31
  133. data/test/support/ssl/trusted-ca.crt +0 -25
  134. data/test/support/ssl/trusted-ca.key +0 -27
  135. data/test/support/ssl/trusted-cert.crt +0 -81
  136. data/test/support/ssl/trusted-cert.key +0 -28
  137. data/test/support/ssl/untrusted-ca.crt +0 -26
  138. data/test/support/ssl/untrusted-ca.key +0 -27
  139. data/test/support/ssl/untrusted-cert.crt +0 -82
  140. data/test/support/ssl/untrusted-cert.key +0 -28
  141. data/test/support/wire/synchrony.rb +0 -24
  142. data/test/support/wire/thread.rb +0 -5
  143. data/test/synchrony_driver.rb +0 -85
  144. data/test/test.conf.erb +0 -9
  145. data/test/thread_safety_test.rb +0 -60
  146. data/test/transactions_test.rb +0 -262
  147. data/test/unknown_commands_test.rb +0 -12
  148. data/test/url_param_test.rb +0 -136
@@ -1,56 +0,0 @@
1
- require_relative "helper"
2
-
3
- class TestDistributed < Test::Unit::TestCase
4
-
5
- include Helper::Distributed
6
-
7
- def test_handle_multiple_servers
8
- @r = Redis::Distributed.new ["redis://127.0.0.1:#{PORT}/15", *NODES]
9
-
10
- 100.times do |idx|
11
- @r.set(idx.to_s, "foo#{idx}")
12
- end
13
-
14
- 100.times do |idx|
15
- assert_equal "foo#{idx}", @r.get(idx.to_s)
16
- end
17
-
18
- assert_equal "0", @r.keys("*").sort.first
19
- assert_equal "string", @r.type("1")
20
- end
21
-
22
- def test_add_nodes
23
- logger = Logger.new("/dev/null")
24
-
25
- @r = Redis::Distributed.new NODES, :logger => logger, :timeout => 10
26
-
27
- assert_equal "127.0.0.1", @r.nodes[0]._client.host
28
- assert_equal PORT, @r.nodes[0]._client.port
29
- assert_equal 15, @r.nodes[0]._client.db
30
- assert_equal 10, @r.nodes[0]._client.timeout
31
- assert_equal logger, @r.nodes[0]._client.logger
32
-
33
- @r.add_node("redis://127.0.0.1:6380/14")
34
-
35
- assert_equal "127.0.0.1", @r.nodes[1]._client.host
36
- assert_equal 6380, @r.nodes[1]._client.port
37
- assert_equal 14, @r.nodes[1]._client.db
38
- assert_equal 10, @r.nodes[1]._client.timeout
39
- assert_equal logger, @r.nodes[1]._client.logger
40
- end
41
-
42
- def test_pipelining_commands_cannot_be_distributed
43
- assert_raise Redis::Distributed::CannotDistribute do
44
- r.pipelined do
45
- r.lpush "foo", "s1"
46
- r.lpush "foo", "s2"
47
- end
48
- end
49
- end
50
-
51
- def test_unknown_commands_does_not_work_by_default
52
- assert_raise NoMethodError do
53
- r.not_yet_implemented_command
54
- end
55
- end
56
- end
@@ -1,30 +0,0 @@
1
- require_relative "helper"
2
-
3
- class TestDistributedTransactions < Test::Unit::TestCase
4
-
5
- include Helper::Distributed
6
-
7
- def test_multi_discard
8
- @foo = nil
9
-
10
- assert_raise Redis::Distributed::CannotDistribute do
11
- r.multi { @foo = 1 }
12
- end
13
-
14
- assert_equal nil, @foo
15
-
16
- assert_raise Redis::Distributed::CannotDistribute do
17
- r.discard
18
- end
19
- end
20
-
21
- def test_watch_unwatch
22
- assert_raise Redis::Distributed::CannotDistribute do
23
- r.watch("foo")
24
- end
25
-
26
- assert_raise Redis::Distributed::CannotDistribute do
27
- r.unwatch
28
- end
29
- end
30
- end
@@ -1,14 +0,0 @@
1
- require_relative "helper"
2
-
3
- class TestEncoding < Test::Unit::TestCase
4
-
5
- include Helper::Client
6
-
7
- def test_returns_properly_encoded_strings
8
- with_external_encoding("UTF-8") do
9
- r.set "foo", "שלום"
10
-
11
- assert_equal "Shalom שלום", "Shalom " + r.get("foo")
12
- end
13
- end
14
- end
@@ -1,57 +0,0 @@
1
- require_relative "helper"
2
-
3
- class TestErrorReplies < Test::Unit::TestCase
4
-
5
- include Helper::Client
6
-
7
- # Every test shouldn't disconnect from the server. Also, when error replies are
8
- # in play, the protocol should never get into an invalid state where there are
9
- # pending replies in the connection. Calling INFO after every test ensures that
10
- # the protocol is still in a valid state.
11
- def with_reconnection_check
12
- before = r.info["total_connections_received"]
13
- yield(r)
14
- after = r.info["total_connections_received"]
15
- ensure
16
- assert_equal before, after
17
- end
18
-
19
- def test_error_reply_for_single_command
20
- with_reconnection_check do
21
- begin
22
- r.unknown_command
23
- rescue => ex
24
- ensure
25
- assert ex.message =~ /unknown command/i
26
- end
27
- end
28
- end
29
-
30
- def test_raise_first_error_reply_in_pipeline
31
- with_reconnection_check do
32
- begin
33
- r.pipelined do
34
- r.set("foo", "s1")
35
- r.incr("foo") # not an integer
36
- r.lpush("foo", "value") # wrong kind of value
37
- end
38
- rescue => ex
39
- ensure
40
- assert ex.message =~ /not an integer/i
41
- end
42
- end
43
- end
44
-
45
- def test_recover_from_raise_in__call_loop
46
- with_reconnection_check do
47
- begin
48
- r._client.call_loop([:invalid_monitor]) do
49
- assert false # Should never be executed
50
- end
51
- rescue => ex
52
- ensure
53
- assert ex.message =~ /unknown command/i
54
- end
55
- end
56
- end
57
- end
@@ -1,60 +0,0 @@
1
- require_relative "helper"
2
-
3
- class TestForkSafety < Test::Unit::TestCase
4
-
5
- include Helper::Client
6
-
7
- driver(:ruby, :hiredis) do
8
- def test_fork_safety
9
- redis = Redis.new(OPTIONS)
10
- redis.set "foo", 1
11
-
12
- child_pid = fork do
13
- begin
14
- # InheritedError triggers a reconnect,
15
- # so we need to disable reconnects to force
16
- # the exception bubble up
17
- redis.without_reconnect do
18
- redis.set "foo", 2
19
- end
20
- rescue Redis::InheritedError
21
- exit 127
22
- end
23
- end
24
-
25
- _, status = Process.wait2(child_pid)
26
-
27
- assert_equal 127, status.exitstatus
28
- assert_equal "1", redis.get("foo")
29
-
30
- rescue NotImplementedError => error
31
- raise unless error.message =~ /fork is not available/
32
- end
33
-
34
- def test_fork_safety_with_enabled_inherited_socket
35
- redis = Redis.new(OPTIONS.merge(:inherit_socket => true))
36
- redis.set "foo", 1
37
-
38
- child_pid = fork do
39
- begin
40
- # InheritedError triggers a reconnect,
41
- # so we need to disable reconnects to force
42
- # the exception bubble up
43
- redis.without_reconnect do
44
- redis.set "foo", 2
45
- end
46
- rescue Redis::InheritedError
47
- exit 127
48
- end
49
- end
50
-
51
- _, status = Process.wait2(child_pid)
52
-
53
- assert_equal 0, status.exitstatus
54
- assert_equal "2", redis.get("foo")
55
-
56
- rescue NotImplementedError => error
57
- raise unless error.message =~ /fork is not available/
58
- end
59
- end
60
- end
data/test/helper.rb DELETED
@@ -1,201 +0,0 @@
1
- require "test/unit"
2
- require "logger"
3
- require "stringio"
4
-
5
- $VERBOSE = true
6
-
7
- ENV["DRIVER"] ||= "ruby"
8
-
9
- require_relative "../lib/redis"
10
- require_relative "../lib/redis/distributed"
11
- require_relative "../lib/redis/connection/#{ENV["DRIVER"]}"
12
-
13
- require_relative "support/redis_mock"
14
- require_relative "support/connection/#{ENV["DRIVER"]}"
15
-
16
- PORT = 6381
17
- OPTIONS = {:port => PORT, :db => 15, :timeout => Float(ENV["TIMEOUT"] || 0.1)}
18
- NODES = ["redis://127.0.0.1:#{PORT}/15"]
19
-
20
- def init(redis)
21
- begin
22
- redis.select 14
23
- redis.flushdb
24
- redis.select 15
25
- redis.flushdb
26
- redis
27
- rescue Redis::CannotConnectError
28
- puts <<-EOS
29
-
30
- Cannot connect to Redis.
31
-
32
- Make sure Redis is running on localhost, port #{PORT}.
33
- This testing suite connects to the database 15.
34
-
35
- Try this once:
36
-
37
- $ make clean
38
-
39
- Then run the build again:
40
-
41
- $ make
42
-
43
- EOS
44
- exit 1
45
- end
46
- end
47
-
48
- def driver(*drivers, &blk)
49
- if drivers.map(&:to_s).include?(ENV["DRIVER"])
50
- class_eval(&blk)
51
- end
52
- end
53
-
54
- module Helper
55
-
56
- def run(runner)
57
- if respond_to?(:around)
58
- around { super(runner) }
59
- else
60
- super
61
- end
62
- end
63
-
64
- def silent
65
- verbose, $VERBOSE = $VERBOSE, false
66
-
67
- begin
68
- yield
69
- ensure
70
- $VERBOSE = verbose
71
- end
72
- end
73
-
74
- def with_external_encoding(encoding)
75
- original_encoding = Encoding.default_external
76
-
77
- begin
78
- silent { Encoding.default_external = Encoding.find(encoding) }
79
- yield
80
- ensure
81
- silent { Encoding.default_external = original_encoding }
82
- end
83
- end
84
-
85
- class Version
86
-
87
- include Comparable
88
-
89
- attr :parts
90
-
91
- def initialize(v)
92
- case v
93
- when Version
94
- @parts = v.parts
95
- else
96
- @parts = v.to_s.split(".")
97
- end
98
- end
99
-
100
- def <=>(other)
101
- other = Version.new(other)
102
- length = [self.parts.length, other.parts.length].max
103
- length.times do |i|
104
- a, b = self.parts[i], other.parts[i]
105
-
106
- return -1 if a.nil?
107
- return +1 if b.nil?
108
- return a.to_i <=> b.to_i if a != b
109
- end
110
-
111
- 0
112
- end
113
- end
114
-
115
- module Generic
116
-
117
- include Helper
118
-
119
- attr_reader :log
120
- attr_reader :redis
121
-
122
- alias :r :redis
123
-
124
- def setup
125
- @log = StringIO.new
126
- @redis = init _new_client
127
-
128
- # Run GC to make sure orphaned connections are closed.
129
- GC.start
130
- end
131
-
132
- def teardown
133
- @redis.quit if @redis
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
- end
160
-
161
- module Client
162
-
163
- include Generic
164
-
165
- def version
166
- Version.new(redis.info["redis_version"])
167
- end
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
- 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