redis 3.2.0 → 4.6.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 (133) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +278 -15
  3. data/README.md +260 -76
  4. data/lib/redis/client.rb +239 -115
  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 +37 -0
  11. data/lib/redis/cluster/option.rb +93 -0
  12. data/lib/redis/cluster/slot.rb +86 -0
  13. data/lib/redis/cluster/slot_loader.rb +49 -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 +411 -0
  22. data/lib/redis/commands/lists.rb +289 -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 +207 -0
  27. data/lib/redis/commands/sorted_sets.rb +804 -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 +92 -0
  31. data/lib/redis/commands.rb +242 -0
  32. data/lib/redis/connection/command_helper.rb +7 -10
  33. data/lib/redis/connection/hiredis.rb +11 -6
  34. data/lib/redis/connection/registry.rb +2 -1
  35. data/lib/redis/connection/ruby.rb +173 -64
  36. data/lib/redis/connection/synchrony.rb +32 -8
  37. data/lib/redis/connection.rb +3 -1
  38. data/lib/redis/distributed.rb +233 -74
  39. data/lib/redis/errors.rb +48 -0
  40. data/lib/redis/hash_ring.rb +30 -72
  41. data/lib/redis/pipeline.rb +145 -12
  42. data/lib/redis/subscribe.rb +20 -13
  43. data/lib/redis/version.rb +3 -1
  44. data/lib/redis.rb +171 -2476
  45. metadata +71 -165
  46. data/.gitignore +0 -15
  47. data/.travis/Gemfile +0 -11
  48. data/.travis.yml +0 -54
  49. data/.yardopts +0 -3
  50. data/Gemfile +0 -4
  51. data/Rakefile +0 -68
  52. data/benchmarking/logging.rb +0 -71
  53. data/benchmarking/pipeline.rb +0 -51
  54. data/benchmarking/speed.rb +0 -21
  55. data/benchmarking/suite.rb +0 -24
  56. data/benchmarking/worker.rb +0 -71
  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/redis.gemspec +0 -43
  70. data/test/bitpos_test.rb +0 -69
  71. data/test/blocking_commands_test.rb +0 -42
  72. data/test/command_map_test.rb +0 -30
  73. data/test/commands_on_hashes_test.rb +0 -21
  74. data/test/commands_on_hyper_log_log_test.rb +0 -21
  75. data/test/commands_on_lists_test.rb +0 -20
  76. data/test/commands_on_sets_test.rb +0 -77
  77. data/test/commands_on_sorted_sets_test.rb +0 -123
  78. data/test/commands_on_strings_test.rb +0 -101
  79. data/test/commands_on_value_types_test.rb +0 -131
  80. data/test/connection_handling_test.rb +0 -189
  81. data/test/db/.gitkeep +0 -0
  82. data/test/distributed_blocking_commands_test.rb +0 -46
  83. data/test/distributed_commands_on_hashes_test.rb +0 -10
  84. data/test/distributed_commands_on_hyper_log_log_test.rb +0 -33
  85. data/test/distributed_commands_on_lists_test.rb +0 -22
  86. data/test/distributed_commands_on_sets_test.rb +0 -83
  87. data/test/distributed_commands_on_sorted_sets_test.rb +0 -18
  88. data/test/distributed_commands_on_strings_test.rb +0 -59
  89. data/test/distributed_commands_on_value_types_test.rb +0 -95
  90. data/test/distributed_commands_requiring_clustering_test.rb +0 -164
  91. data/test/distributed_connection_handling_test.rb +0 -23
  92. data/test/distributed_internals_test.rb +0 -70
  93. data/test/distributed_key_tags_test.rb +0 -52
  94. data/test/distributed_persistence_control_commands_test.rb +0 -26
  95. data/test/distributed_publish_subscribe_test.rb +0 -92
  96. data/test/distributed_remote_server_control_commands_test.rb +0 -66
  97. data/test/distributed_scripting_test.rb +0 -102
  98. data/test/distributed_sorting_test.rb +0 -20
  99. data/test/distributed_test.rb +0 -58
  100. data/test/distributed_transactions_test.rb +0 -32
  101. data/test/encoding_test.rb +0 -18
  102. data/test/error_replies_test.rb +0 -59
  103. data/test/fork_safety_test.rb +0 -65
  104. data/test/helper.rb +0 -232
  105. data/test/helper_test.rb +0 -24
  106. data/test/internals_test.rb +0 -434
  107. data/test/lint/blocking_commands.rb +0 -150
  108. data/test/lint/hashes.rb +0 -162
  109. data/test/lint/hyper_log_log.rb +0 -60
  110. data/test/lint/lists.rb +0 -143
  111. data/test/lint/sets.rb +0 -125
  112. data/test/lint/sorted_sets.rb +0 -238
  113. data/test/lint/strings.rb +0 -260
  114. data/test/lint/value_types.rb +0 -122
  115. data/test/persistence_control_commands_test.rb +0 -26
  116. data/test/pipelining_commands_test.rb +0 -242
  117. data/test/publish_subscribe_test.rb +0 -210
  118. data/test/remote_server_control_commands_test.rb +0 -117
  119. data/test/scanning_test.rb +0 -413
  120. data/test/scripting_test.rb +0 -78
  121. data/test/sorting_test.rb +0 -59
  122. data/test/support/connection/hiredis.rb +0 -1
  123. data/test/support/connection/ruby.rb +0 -1
  124. data/test/support/connection/synchrony.rb +0 -17
  125. data/test/support/redis_mock.rb +0 -115
  126. data/test/support/wire/synchrony.rb +0 -24
  127. data/test/support/wire/thread.rb +0 -5
  128. data/test/synchrony_driver.rb +0 -88
  129. data/test/test.conf +0 -9
  130. data/test/thread_safety_test.rb +0 -32
  131. data/test/transactions_test.rb +0 -264
  132. data/test/unknown_commands_test.rb +0 -14
  133. data/test/url_param_test.rb +0 -132
@@ -1,242 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require File.expand_path("helper", File.dirname(__FILE__))
4
-
5
- class TestPipeliningCommands < Test::Unit::TestCase
6
-
7
- include Helper::Client
8
-
9
- def test_bulk_commands
10
- r.pipelined do
11
- r.lpush "foo", "s1"
12
- r.lpush "foo", "s2"
13
- end
14
-
15
- assert_equal 2, r.llen("foo")
16
- assert_equal "s2", r.lpop("foo")
17
- assert_equal "s1", r.lpop("foo")
18
- end
19
-
20
- def test_multi_bulk_commands
21
- r.pipelined do
22
- r.mset("foo", "s1", "bar", "s2")
23
- r.mset("baz", "s3", "qux", "s4")
24
- end
25
-
26
- assert_equal "s1", r.get("foo")
27
- assert_equal "s2", r.get("bar")
28
- assert_equal "s3", r.get("baz")
29
- assert_equal "s4", r.get("qux")
30
- end
31
-
32
- def test_bulk_and_multi_bulk_commands_mixed
33
- r.pipelined do
34
- r.lpush "foo", "s1"
35
- r.lpush "foo", "s2"
36
- r.mset("baz", "s3", "qux", "s4")
37
- end
38
-
39
- assert_equal 2, r.llen("foo")
40
- assert_equal "s2", r.lpop("foo")
41
- assert_equal "s1", r.lpop("foo")
42
- assert_equal "s3", r.get("baz")
43
- assert_equal "s4", r.get("qux")
44
- end
45
-
46
- def test_multi_bulk_and_bulk_commands_mixed
47
- r.pipelined do
48
- r.mset("baz", "s3", "qux", "s4")
49
- r.lpush "foo", "s1"
50
- r.lpush "foo", "s2"
51
- end
52
-
53
- assert_equal 2, r.llen("foo")
54
- assert_equal "s2", r.lpop("foo")
55
- assert_equal "s1", r.lpop("foo")
56
- assert_equal "s3", r.get("baz")
57
- assert_equal "s4", r.get("qux")
58
- end
59
-
60
- def test_pipelined_with_an_empty_block
61
- assert_nothing_raised do
62
- r.pipelined do
63
- end
64
- end
65
-
66
- assert_equal 0, r.dbsize
67
- end
68
-
69
- def test_returning_the_result_of_a_pipeline
70
- result = r.pipelined do
71
- r.set "foo", "bar"
72
- r.get "foo"
73
- r.get "bar"
74
- end
75
-
76
- assert_equal ["OK", "bar", nil], result
77
- end
78
-
79
- def test_assignment_of_results_inside_the_block
80
- r.pipelined do
81
- @first = r.sadd("foo", 1)
82
- @second = r.sadd("foo", 1)
83
- end
84
-
85
- assert_equal true, @first.value
86
- assert_equal false, @second.value
87
- end
88
-
89
- # Although we could support accessing the values in these futures,
90
- # it doesn't make a lot of sense.
91
- def test_assignment_of_results_inside_the_block_with_errors
92
- assert_raise(Redis::CommandError) do
93
- r.pipelined do
94
- r.doesnt_exist
95
- @first = r.sadd("foo", 1)
96
- @second = r.sadd("foo", 1)
97
- end
98
- end
99
-
100
- assert_raise(Redis::FutureNotReady) { @first.value }
101
- assert_raise(Redis::FutureNotReady) { @second.value }
102
- end
103
-
104
- def test_assignment_of_results_inside_a_nested_block
105
- r.pipelined do
106
- @first = r.sadd("foo", 1)
107
-
108
- r.pipelined do
109
- @second = r.sadd("foo", 1)
110
- end
111
- end
112
-
113
- assert_equal true, @first.value
114
- assert_equal false, @second.value
115
- end
116
-
117
- def test_futures_raise_when_confused_with_something_else
118
- r.pipelined do
119
- @result = r.sadd("foo", 1)
120
- end
121
-
122
- assert_raise(NoMethodError) { @result.to_s }
123
- end
124
-
125
- def test_futures_raise_when_trying_to_access_their_values_too_early
126
- r.pipelined do
127
- assert_raise(Redis::FutureNotReady) do
128
- r.sadd("foo", 1).value
129
- end
130
- end
131
- end
132
-
133
- def test_futures_can_be_identified
134
- r.pipelined do
135
- @result = r.sadd("foo", 1)
136
- end
137
-
138
- assert_equal true, @result.is_a?(Redis::Future)
139
- if defined?(::BasicObject)
140
- assert_equal true, @result.is_a?(::BasicObject)
141
- end
142
- assert_equal Redis::Future, @result.class
143
- end
144
-
145
- def test_returning_the_result_of_an_empty_pipeline
146
- result = r.pipelined do
147
- end
148
-
149
- assert_equal [], result
150
- end
151
-
152
- def test_nesting_pipeline_blocks
153
- r.pipelined do
154
- r.set("foo", "s1")
155
- r.pipelined do
156
- r.set("bar", "s2")
157
- end
158
- end
159
-
160
- assert_equal "s1", r.get("foo")
161
- assert_equal "s2", r.get("bar")
162
- end
163
-
164
- def test_info_in_a_pipeline_returns_hash
165
- result = r.pipelined do
166
- r.info
167
- end
168
-
169
- assert result.first.kind_of?(Hash)
170
- end
171
-
172
- def test_config_get_in_a_pipeline_returns_hash
173
- result = r.pipelined do
174
- r.config(:get, "*")
175
- end
176
-
177
- assert result.first.kind_of?(Hash)
178
- end
179
-
180
- def test_hgetall_in_a_pipeline_returns_hash
181
- r.hmset("hash", "field", "value")
182
- result = r.pipelined do
183
- r.hgetall("hash")
184
- end
185
-
186
- assert_equal result.first, { "field" => "value" }
187
- end
188
-
189
- def test_keys_in_a_pipeline
190
- r.set("key", "value")
191
- result = r.pipelined do
192
- r.keys("*")
193
- end
194
-
195
- assert_equal ["key"], result.first
196
- end
197
-
198
- def test_pipeline_yields_a_connection
199
- r.pipelined do |p|
200
- p.set("foo", "bar")
201
- end
202
-
203
- assert_equal "bar", r.get("foo")
204
- end
205
-
206
- def test_pipeline_select
207
- r.select 1
208
- r.set("db", "1")
209
-
210
- r.pipelined do |p|
211
- p.select 2
212
- p.set("db", "2")
213
- end
214
-
215
- r.select 1
216
- assert_equal "1", r.get("db")
217
-
218
- r.select 2
219
- assert_equal "2", r.get("db")
220
- end
221
-
222
- def test_pipeline_select_client_db
223
- r.select 1
224
- r.pipelined do |p2|
225
- p2.select 2
226
- end
227
-
228
- assert_equal 2, r.client.db
229
- end
230
-
231
- def test_nested_pipeline_select_client_db
232
- r.select 1
233
- r.pipelined do |p2|
234
- p2.select 2
235
- p2.pipelined do |p3|
236
- p3.select 3
237
- end
238
- end
239
-
240
- assert_equal 3, r.client.db
241
- end
242
- end
@@ -1,210 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require File.expand_path("helper", File.dirname(__FILE__))
4
-
5
- class TestPublishSubscribe < Test::Unit::TestCase
6
-
7
- include Helper::Client
8
-
9
- class TestError < StandardError
10
- end
11
-
12
- def test_subscribe_and_unsubscribe
13
- @subscribed = false
14
- @unsubscribed = false
15
-
16
- wire = Wire.new do
17
- r.subscribe("foo") do |on|
18
- on.subscribe do |channel, total|
19
- @subscribed = true
20
- @t1 = total
21
- end
22
-
23
- on.message do |channel, message|
24
- if message == "s1"
25
- r.unsubscribe
26
- @message = message
27
- end
28
- end
29
-
30
- on.unsubscribe do |channel, total|
31
- @unsubscribed = true
32
- @t2 = total
33
- end
34
- end
35
- end
36
-
37
- # Wait until the subscription is active before publishing
38
- Wire.pass while !@subscribed
39
-
40
- Redis.new(OPTIONS).publish("foo", "s1")
41
-
42
- wire.join
43
-
44
- assert @subscribed
45
- assert_equal 1, @t1
46
- assert @unsubscribed
47
- assert_equal 0, @t2
48
- assert_equal "s1", @message
49
- end
50
-
51
- def test_psubscribe_and_punsubscribe
52
- @subscribed = false
53
- @unsubscribed = false
54
-
55
- wire = Wire.new do
56
- r.psubscribe("f*") do |on|
57
- on.psubscribe do |pattern, total|
58
- @subscribed = true
59
- @t1 = total
60
- end
61
-
62
- on.pmessage do |pattern, channel, message|
63
- if message == "s1"
64
- r.punsubscribe
65
- @message = message
66
- end
67
- end
68
-
69
- on.punsubscribe do |pattern, total|
70
- @unsubscribed = true
71
- @t2 = total
72
- end
73
- end
74
- end
75
-
76
- # Wait until the subscription is active before publishing
77
- Wire.pass while !@subscribed
78
-
79
- Redis.new(OPTIONS).publish("foo", "s1")
80
-
81
- wire.join
82
-
83
- assert @subscribed
84
- assert_equal 1, @t1
85
- assert @unsubscribed
86
- assert_equal 0, @t2
87
- assert_equal "s1", @message
88
- end
89
-
90
- def test_subscribe_connection_usable_after_raise
91
- @subscribed = false
92
-
93
- wire = Wire.new do
94
- begin
95
- r.subscribe("foo") do |on|
96
- on.subscribe do |channel, total|
97
- @subscribed = true
98
- end
99
-
100
- on.message do |channel, message|
101
- raise TestError
102
- end
103
- end
104
- rescue TestError
105
- end
106
- end
107
-
108
- # Wait until the subscription is active before publishing
109
- Wire.pass while !@subscribed
110
-
111
- Redis.new(OPTIONS).publish("foo", "s1")
112
-
113
- wire.join
114
-
115
- assert_equal "PONG", r.ping
116
- end
117
-
118
- def test_psubscribe_connection_usable_after_raise
119
- @subscribed = false
120
-
121
- wire = Wire.new do
122
- begin
123
- r.psubscribe("f*") do |on|
124
- on.psubscribe do |pattern, total|
125
- @subscribed = true
126
- end
127
-
128
- on.pmessage do |pattern, channel, message|
129
- raise TestError
130
- end
131
- end
132
- rescue TestError
133
- end
134
- end
135
-
136
- # Wait until the subscription is active before publishing
137
- Wire.pass while !@subscribed
138
-
139
- Redis.new(OPTIONS).publish("foo", "s1")
140
-
141
- wire.join
142
-
143
- assert_equal "PONG", r.ping
144
- end
145
-
146
- def test_subscribe_within_subscribe
147
- @channels = []
148
-
149
- wire = Wire.new do
150
- r.subscribe("foo") do |on|
151
- on.subscribe do |channel, total|
152
- @channels << channel
153
-
154
- r.subscribe("bar") if channel == "foo"
155
- r.unsubscribe if channel == "bar"
156
- end
157
- end
158
- end
159
-
160
- wire.join
161
-
162
- assert_equal ["foo", "bar"], @channels
163
- end
164
-
165
- def test_other_commands_within_a_subscribe
166
- assert_raise Redis::CommandError do
167
- r.subscribe("foo") do |on|
168
- on.subscribe do |channel, total|
169
- r.set("bar", "s2")
170
- end
171
- end
172
- end
173
- end
174
-
175
- def test_subscribe_without_a_block
176
- assert_raise LocalJumpError do
177
- r.subscribe("foo")
178
- end
179
- end
180
-
181
- def test_unsubscribe_without_a_subscribe
182
- assert_raise RuntimeError do
183
- r.unsubscribe
184
- end
185
-
186
- assert_raise RuntimeError do
187
- r.punsubscribe
188
- end
189
- end
190
-
191
- def test_subscribe_past_a_timeout
192
- # For some reason, a thread here doesn't reproduce the issue.
193
- sleep = %{sleep #{OPTIONS[:timeout] * 2}}
194
- publish = %{ruby -rsocket -e 't=TCPSocket.new("127.0.0.1",#{OPTIONS[:port]});t.write("publish foo bar\\r\\n");t.read(4);t.close'}
195
- cmd = [sleep, publish].join("; ")
196
-
197
- IO.popen(cmd, "r+") do |pipe|
198
- received = false
199
-
200
- r.subscribe "foo" do |on|
201
- on.message do |channel, message|
202
- received = true
203
- r.unsubscribe
204
- end
205
- end
206
-
207
- assert received
208
- end
209
- end
210
- end
@@ -1,117 +0,0 @@
1
- # encoding: UTF-8
2
-
3
- require File.expand_path("helper", File.dirname(__FILE__))
4
-
5
- class TestRemoteServerControlCommands < Test::Unit::TestCase
6
-
7
- include Helper::Client
8
-
9
- def test_info
10
- keys = [
11
- "redis_version",
12
- "uptime_in_seconds",
13
- "uptime_in_days",
14
- "connected_clients",
15
- "used_memory",
16
- "total_connections_received",
17
- "total_commands_processed",
18
- ]
19
-
20
- info = r.info
21
-
22
- keys.each do |k|
23
- msg = "expected #info to include #{k}"
24
- assert info.keys.include?(k), msg
25
- end
26
- end
27
-
28
- def test_info_commandstats
29
- target_version "2.5.7" do
30
- r.config(:resetstat)
31
- r.ping
32
-
33
- result = r.info(:commandstats)
34
- assert_equal "1", result["ping"]["calls"]
35
- end
36
- end
37
-
38
- def test_monitor_redis_lt_2_5_0
39
- return unless version < "2.5.0"
40
-
41
- log = []
42
-
43
- wire = Wire.new do
44
- Redis.new(OPTIONS).monitor do |line|
45
- log << line
46
- break if log.size == 3
47
- end
48
- end
49
-
50
- Wire.pass while log.empty? # Faster than sleep
51
-
52
- r.set "foo", "s1"
53
-
54
- wire.join
55
-
56
- assert log[-1][%q{(db 15) "set" "foo" "s1"}]
57
- end
58
-
59
- def test_monitor_redis_gte_2_5_0
60
- return unless version >= "2.5.0"
61
-
62
- log = []
63
-
64
- wire = Wire.new do
65
- Redis.new(OPTIONS).monitor do |line|
66
- log << line
67
- break if line =~ /set/
68
- end
69
- end
70
-
71
- Wire.pass while log.empty? # Faster than sleep
72
-
73
- r.set "foo", "s1"
74
-
75
- wire.join
76
-
77
- assert log[-1] =~ /\b15\b.* "set" "foo" "s1"/
78
- end
79
-
80
- def test_monitor_returns_value_for_break
81
- result = r.monitor do |line|
82
- break line
83
- end
84
-
85
- assert_equal result, "OK"
86
- end
87
-
88
- def test_echo
89
- assert_equal "foo bar baz\n", r.echo("foo bar baz\n")
90
- end
91
-
92
- def test_debug
93
- r.set "foo", "s1"
94
-
95
- assert r.debug(:object, "foo").kind_of?(String)
96
- end
97
-
98
- def test_object
99
- r.lpush "list", "value"
100
-
101
- assert_equal r.object(:refcount, "list"), 1
102
- assert_equal r.object(:encoding, "list"), "ziplist"
103
- assert r.object(:idletime, "list").kind_of?(Fixnum)
104
- end
105
-
106
- def test_sync
107
- redis_mock(:sync => lambda { "+OK" }) do |redis|
108
- assert_equal "OK", redis.sync
109
- end
110
- end
111
-
112
- def test_slowlog
113
- r.slowlog(:reset)
114
- result = r.slowlog(:len)
115
- assert_equal result, 0
116
- end
117
- end