discourse-redis 3.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (107) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +16 -0
  3. data/.travis.yml +59 -0
  4. data/.travis/Gemfile +11 -0
  5. data/.yardopts +3 -0
  6. data/CHANGELOG.md +349 -0
  7. data/Gemfile +4 -0
  8. data/LICENSE +20 -0
  9. data/README.md +328 -0
  10. data/Rakefile +87 -0
  11. data/benchmarking/logging.rb +71 -0
  12. data/benchmarking/pipeline.rb +51 -0
  13. data/benchmarking/speed.rb +21 -0
  14. data/benchmarking/suite.rb +24 -0
  15. data/benchmarking/worker.rb +71 -0
  16. data/examples/basic.rb +15 -0
  17. data/examples/consistency.rb +114 -0
  18. data/examples/dist_redis.rb +43 -0
  19. data/examples/incr-decr.rb +17 -0
  20. data/examples/list.rb +26 -0
  21. data/examples/pubsub.rb +37 -0
  22. data/examples/sentinel.rb +41 -0
  23. data/examples/sentinel/start +49 -0
  24. data/examples/sets.rb +36 -0
  25. data/examples/unicorn/config.ru +3 -0
  26. data/examples/unicorn/unicorn.rb +20 -0
  27. data/lib/redis.rb +2731 -0
  28. data/lib/redis/client.rb +575 -0
  29. data/lib/redis/connection.rb +9 -0
  30. data/lib/redis/connection/command_helper.rb +44 -0
  31. data/lib/redis/connection/hiredis.rb +64 -0
  32. data/lib/redis/connection/registry.rb +12 -0
  33. data/lib/redis/connection/ruby.rb +322 -0
  34. data/lib/redis/connection/synchrony.rb +124 -0
  35. data/lib/redis/distributed.rb +873 -0
  36. data/lib/redis/errors.rb +40 -0
  37. data/lib/redis/hash_ring.rb +132 -0
  38. data/lib/redis/pipeline.rb +141 -0
  39. data/lib/redis/subscribe.rb +83 -0
  40. data/lib/redis/version.rb +3 -0
  41. data/redis.gemspec +34 -0
  42. data/test/bitpos_test.rb +69 -0
  43. data/test/blocking_commands_test.rb +42 -0
  44. data/test/command_map_test.rb +30 -0
  45. data/test/commands_on_hashes_test.rb +21 -0
  46. data/test/commands_on_hyper_log_log_test.rb +21 -0
  47. data/test/commands_on_lists_test.rb +20 -0
  48. data/test/commands_on_sets_test.rb +77 -0
  49. data/test/commands_on_sorted_sets_test.rb +137 -0
  50. data/test/commands_on_strings_test.rb +101 -0
  51. data/test/commands_on_value_types_test.rb +133 -0
  52. data/test/connection_handling_test.rb +250 -0
  53. data/test/distributed_blocking_commands_test.rb +46 -0
  54. data/test/distributed_commands_on_hashes_test.rb +10 -0
  55. data/test/distributed_commands_on_hyper_log_log_test.rb +33 -0
  56. data/test/distributed_commands_on_lists_test.rb +22 -0
  57. data/test/distributed_commands_on_sets_test.rb +83 -0
  58. data/test/distributed_commands_on_sorted_sets_test.rb +18 -0
  59. data/test/distributed_commands_on_strings_test.rb +59 -0
  60. data/test/distributed_commands_on_value_types_test.rb +95 -0
  61. data/test/distributed_commands_requiring_clustering_test.rb +164 -0
  62. data/test/distributed_connection_handling_test.rb +23 -0
  63. data/test/distributed_internals_test.rb +79 -0
  64. data/test/distributed_key_tags_test.rb +52 -0
  65. data/test/distributed_persistence_control_commands_test.rb +26 -0
  66. data/test/distributed_publish_subscribe_test.rb +92 -0
  67. data/test/distributed_remote_server_control_commands_test.rb +66 -0
  68. data/test/distributed_scripting_test.rb +102 -0
  69. data/test/distributed_sorting_test.rb +20 -0
  70. data/test/distributed_test.rb +58 -0
  71. data/test/distributed_transactions_test.rb +32 -0
  72. data/test/encoding_test.rb +18 -0
  73. data/test/error_replies_test.rb +59 -0
  74. data/test/fork_safety_test.rb +65 -0
  75. data/test/helper.rb +232 -0
  76. data/test/helper_test.rb +24 -0
  77. data/test/internals_test.rb +437 -0
  78. data/test/lint/blocking_commands.rb +150 -0
  79. data/test/lint/hashes.rb +162 -0
  80. data/test/lint/hyper_log_log.rb +60 -0
  81. data/test/lint/lists.rb +143 -0
  82. data/test/lint/sets.rb +125 -0
  83. data/test/lint/sorted_sets.rb +316 -0
  84. data/test/lint/strings.rb +260 -0
  85. data/test/lint/value_types.rb +122 -0
  86. data/test/persistence_control_commands_test.rb +26 -0
  87. data/test/pipelining_commands_test.rb +242 -0
  88. data/test/publish_subscribe_test.rb +254 -0
  89. data/test/remote_server_control_commands_test.rb +118 -0
  90. data/test/scanning_test.rb +413 -0
  91. data/test/scripting_test.rb +78 -0
  92. data/test/sentinel_command_test.rb +80 -0
  93. data/test/sentinel_test.rb +255 -0
  94. data/test/sorting_test.rb +59 -0
  95. data/test/support/connection/hiredis.rb +1 -0
  96. data/test/support/connection/ruby.rb +1 -0
  97. data/test/support/connection/synchrony.rb +17 -0
  98. data/test/support/redis_mock.rb +119 -0
  99. data/test/support/wire/synchrony.rb +24 -0
  100. data/test/support/wire/thread.rb +5 -0
  101. data/test/synchrony_driver.rb +88 -0
  102. data/test/test.conf.erb +9 -0
  103. data/test/thread_safety_test.rb +32 -0
  104. data/test/transactions_test.rb +264 -0
  105. data/test/unknown_commands_test.rb +14 -0
  106. data/test/url_param_test.rb +138 -0
  107. metadata +182 -0
@@ -0,0 +1,118 @@
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 "OK", result
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 1, r.object(:refcount, "list")
102
+ encoding = r.object(:encoding, "list")
103
+ assert "ziplist" == encoding || "quicklist" == encoding, "Wrong encoding for list"
104
+ assert r.object(:idletime, "list").kind_of?(Fixnum)
105
+ end
106
+
107
+ def test_sync
108
+ redis_mock(:sync => lambda { "+OK" }) do |redis|
109
+ assert_equal "OK", redis.sync
110
+ end
111
+ end
112
+
113
+ def test_slowlog
114
+ r.slowlog(:reset)
115
+ result = r.slowlog(:len)
116
+ assert_equal 0, result
117
+ end
118
+ end
@@ -0,0 +1,413 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ unless defined?(Enumerator)
6
+ Enumerator = Enumerable::Enumerator
7
+ end
8
+
9
+ class TestScanning < Test::Unit::TestCase
10
+
11
+ include Helper::Client
12
+
13
+ def test_scan_basic
14
+ target_version "2.7.105" do
15
+ r.debug :populate, 1000
16
+
17
+ cursor = 0
18
+ all_keys = []
19
+ loop {
20
+ cursor, keys = r.scan cursor
21
+ all_keys += keys
22
+ break if cursor == "0"
23
+ }
24
+
25
+ assert_equal 1000, all_keys.uniq.size
26
+ end
27
+ end
28
+
29
+ def test_scan_count
30
+ target_version "2.7.105" do
31
+ r.debug :populate, 1000
32
+
33
+ cursor = 0
34
+ all_keys = []
35
+ loop {
36
+ cursor, keys = r.scan cursor, :count => 5
37
+ all_keys += keys
38
+ break if cursor == "0"
39
+ }
40
+
41
+ assert_equal 1000, all_keys.uniq.size
42
+ end
43
+ end
44
+
45
+ def test_scan_match
46
+ target_version "2.7.105" do
47
+ r.debug :populate, 1000
48
+
49
+ cursor = 0
50
+ all_keys = []
51
+ loop {
52
+ cursor, keys = r.scan cursor, :match => "key:1??"
53
+ all_keys += keys
54
+ break if cursor == "0"
55
+ }
56
+
57
+ assert_equal 100, all_keys.uniq.size
58
+ end
59
+ end
60
+
61
+ def test_scan_each_enumerator
62
+ target_version "2.7.105" do
63
+
64
+ r.debug :populate, 1000
65
+
66
+ scan_enumerator = r.scan_each
67
+ assert_equal true, scan_enumerator.is_a?(::Enumerator)
68
+
69
+ keys_from_scan = scan_enumerator.to_a.uniq
70
+ all_keys = r.keys "*"
71
+
72
+ assert all_keys.sort == keys_from_scan.sort
73
+ end
74
+ end
75
+
76
+ def test_scan_each_enumerator_match
77
+ target_version "2.7.105" do
78
+
79
+ r.debug :populate, 1000
80
+
81
+ keys_from_scan = r.scan_each(:match => "key:1??").to_a.uniq
82
+ all_keys = r.keys "key:1??"
83
+
84
+ assert all_keys.sort == keys_from_scan.sort
85
+ end
86
+ end
87
+
88
+ def test_scan_each_block
89
+ target_version "2.7.105" do
90
+
91
+ r.debug :populate, 100
92
+
93
+ keys_from_scan = []
94
+ r.scan_each {|key|
95
+ keys_from_scan << key
96
+ }
97
+
98
+ all_keys = r.keys "*"
99
+
100
+ assert all_keys.sort == keys_from_scan.uniq.sort
101
+ end
102
+ end
103
+
104
+ def test_scan_each_block_match
105
+ target_version "2.7.105" do
106
+
107
+ r.debug :populate, 100
108
+
109
+ keys_from_scan = []
110
+ r.scan_each(:match => "key:1?") {|key|
111
+ keys_from_scan << key
112
+ }
113
+
114
+ all_keys = r.keys "key:1?"
115
+
116
+ assert all_keys.sort == keys_from_scan.uniq.sort
117
+ end
118
+ end
119
+
120
+ def test_sscan_with_encoding
121
+ target_version "2.7.105" do
122
+ [:intset, :hashtable].each do |enc|
123
+ r.del "set"
124
+
125
+ prefix = ""
126
+ prefix = "ele:" if enc == :hashtable
127
+
128
+ elements = []
129
+ 100.times { |j| elements << "#{prefix}#{j}" }
130
+
131
+ r.sadd "set", elements
132
+
133
+ assert_equal enc.to_s, r.object("encoding", "set")
134
+
135
+ cursor = 0
136
+ all_keys = []
137
+ loop {
138
+ cursor, keys = r.sscan "set", cursor
139
+ all_keys += keys
140
+ break if cursor == "0"
141
+ }
142
+
143
+ assert_equal 100, all_keys.uniq.size
144
+ end
145
+ end
146
+ end
147
+
148
+ def test_sscan_each_enumerator
149
+ target_version "2.7.105" do
150
+ elements = []
151
+ 100.times { |j| elements << "ele:#{j}" }
152
+ r.sadd "set", elements
153
+
154
+ scan_enumerator = r.sscan_each("set")
155
+ assert_equal true, scan_enumerator.is_a?(::Enumerator)
156
+
157
+ keys_from_scan = scan_enumerator.to_a.uniq
158
+ all_keys = r.smembers("set")
159
+
160
+ assert all_keys.sort == keys_from_scan.sort
161
+ end
162
+ end
163
+
164
+ def test_sscan_each_enumerator_match
165
+ target_version "2.7.105" do
166
+ elements = []
167
+ 100.times { |j| elements << "ele:#{j}" }
168
+ r.sadd "set", elements
169
+
170
+ keys_from_scan = r.sscan_each("set", :match => "ele:1?").to_a.uniq
171
+
172
+ all_keys = r.smembers("set").grep(/^ele:1.$/)
173
+
174
+ assert all_keys.sort == keys_from_scan.sort
175
+ end
176
+ end
177
+
178
+ def test_sscan_each_enumerator_block
179
+ target_version "2.7.105" do
180
+ elements = []
181
+ 100.times { |j| elements << "ele:#{j}" }
182
+ r.sadd "set", elements
183
+
184
+ keys_from_scan = []
185
+ r.sscan_each("set") do |key|
186
+ keys_from_scan << key
187
+ end
188
+
189
+ all_keys = r.smembers("set")
190
+
191
+ assert all_keys.sort == keys_from_scan.uniq.sort
192
+ end
193
+ end
194
+
195
+ def test_sscan_each_enumerator_block_match
196
+ target_version "2.7.105" do
197
+ elements = []
198
+ 100.times { |j| elements << "ele:#{j}" }
199
+ r.sadd "set", elements
200
+
201
+ keys_from_scan = []
202
+ r.sscan_each("set", :match => "ele:1?") do |key|
203
+ keys_from_scan << key
204
+ end
205
+
206
+ all_keys = r.smembers("set").grep(/^ele:1.$/)
207
+
208
+ assert all_keys.sort == keys_from_scan.uniq.sort
209
+ end
210
+ end
211
+
212
+ def test_hscan_with_encoding
213
+ target_version "2.7.105" do
214
+ [:ziplist, :hashtable].each do |enc|
215
+ r.del "set"
216
+
217
+ count = 1000
218
+ count = 30 if enc == :ziplist
219
+
220
+ elements = []
221
+ count.times { |j| elements << "key:#{j}" << j.to_s }
222
+
223
+ r.hmset "hash", *elements
224
+
225
+ assert_equal enc.to_s, r.object("encoding", "hash")
226
+
227
+ cursor = 0
228
+ all_key_values = []
229
+ loop {
230
+ cursor, key_values = r.hscan "hash", cursor
231
+ all_key_values.concat key_values
232
+ break if cursor == "0"
233
+ }
234
+
235
+ keys2 = []
236
+ all_key_values.each do |k, v|
237
+ assert_equal "key:#{v}", k
238
+ keys2 << k
239
+ end
240
+
241
+ assert_equal count, keys2.uniq.size
242
+ end
243
+ end
244
+ end
245
+
246
+ def test_hscan_each_enumerator
247
+ target_version "2.7.105" do
248
+ count = 1000
249
+ elements = []
250
+ count.times { |j| elements << "key:#{j}" << j.to_s }
251
+ r.hmset "hash", *elements
252
+
253
+ scan_enumerator = r.hscan_each("hash")
254
+ assert_equal true, scan_enumerator.is_a?(::Enumerator)
255
+
256
+ keys_from_scan = scan_enumerator.to_a.uniq
257
+ all_keys = r.hgetall("hash").to_a
258
+
259
+ assert all_keys.sort == keys_from_scan.sort
260
+ end
261
+ end
262
+
263
+ def test_hscan_each_enumerator_match
264
+ target_version "2.7.105" do
265
+ count = 100
266
+ elements = []
267
+ count.times { |j| elements << "key:#{j}" << j.to_s }
268
+ r.hmset "hash", *elements
269
+
270
+ keys_from_scan = r.hscan_each("hash", :match => "key:1?").to_a.uniq
271
+ all_keys = r.hgetall("hash").to_a.select{|k,v| k =~ /^key:1.$/}
272
+
273
+ assert all_keys.sort == keys_from_scan.sort
274
+ end
275
+ end
276
+
277
+ def test_hscan_each_block
278
+ target_version "2.7.105" do
279
+ count = 1000
280
+ elements = []
281
+ count.times { |j| elements << "key:#{j}" << j.to_s }
282
+ r.hmset "hash", *elements
283
+
284
+ keys_from_scan = []
285
+ r.hscan_each("hash") do |field, value|
286
+ keys_from_scan << [field, value]
287
+ end
288
+ all_keys = r.hgetall("hash").to_a
289
+
290
+ assert all_keys.sort == keys_from_scan.uniq.sort
291
+ end
292
+ end
293
+
294
+ def test_hscan_each_block_match
295
+ target_version "2.7.105" do
296
+ count = 1000
297
+ elements = []
298
+ count.times { |j| elements << "key:#{j}" << j.to_s }
299
+ r.hmset "hash", *elements
300
+
301
+ keys_from_scan = []
302
+ r.hscan_each("hash", :match => "key:1?") do |field, value|
303
+ keys_from_scan << [field, value]
304
+ end
305
+ all_keys = r.hgetall("hash").to_a.select{|k,v| k =~ /^key:1.$/}
306
+
307
+ assert all_keys.sort == keys_from_scan.uniq.sort
308
+ end
309
+ end
310
+
311
+ def test_zscan_with_encoding
312
+ target_version "2.7.105" do
313
+ [:ziplist, :skiplist].each do |enc|
314
+ r.del "zset"
315
+
316
+ count = 1000
317
+ count = 30 if enc == :ziplist
318
+
319
+ elements = []
320
+ count.times { |j| elements << j << "key:#{j}" }
321
+
322
+ r.zadd "zset", elements
323
+
324
+ assert_equal enc.to_s, r.object("encoding", "zset")
325
+
326
+ cursor = 0
327
+ all_key_scores = []
328
+ loop {
329
+ cursor, key_scores = r.zscan "zset", cursor
330
+ all_key_scores.concat key_scores
331
+ break if cursor == "0"
332
+ }
333
+
334
+ keys2 = []
335
+ all_key_scores.each do |k, v|
336
+ assert_equal true, v.is_a?(Float)
337
+ assert_equal "key:#{Integer(v)}", k
338
+ keys2 << k
339
+ end
340
+
341
+ assert_equal count, keys2.uniq.size
342
+ end
343
+ end
344
+ end
345
+
346
+ def test_zscan_each_enumerator
347
+ target_version "2.7.105" do
348
+ count = 1000
349
+ elements = []
350
+ count.times { |j| elements << j << "key:#{j}" }
351
+ r.zadd "zset", elements
352
+
353
+ scan_enumerator = r.zscan_each "zset"
354
+ assert_equal true, scan_enumerator.is_a?(::Enumerator)
355
+
356
+ scores_from_scan = scan_enumerator.to_a.uniq
357
+ member_scores = r.zrange("zset", 0, -1, :with_scores => true)
358
+
359
+ assert member_scores.sort == scores_from_scan.sort
360
+ end
361
+ end
362
+
363
+ def test_zscan_each_enumerator_match
364
+ target_version "2.7.105" do
365
+ count = 1000
366
+ elements = []
367
+ count.times { |j| elements << j << "key:#{j}" }
368
+ r.zadd "zset", elements
369
+
370
+ scores_from_scan = r.zscan_each("zset", :match => "key:1??").to_a.uniq
371
+ member_scores = r.zrange("zset", 0, -1, :with_scores => true)
372
+ filtered_members = member_scores.select{|k,s| k =~ /^key:1..$/}
373
+
374
+ assert filtered_members.sort == scores_from_scan.sort
375
+ end
376
+ end
377
+
378
+ def test_zscan_each_block
379
+ target_version "2.7.105" do
380
+ count = 1000
381
+ elements = []
382
+ count.times { |j| elements << j << "key:#{j}" }
383
+ r.zadd "zset", elements
384
+
385
+ scores_from_scan = []
386
+ r.zscan_each("zset") do |member, score|
387
+ scores_from_scan << [member, score]
388
+ end
389
+ member_scores = r.zrange("zset", 0, -1, :with_scores => true)
390
+
391
+ assert member_scores.sort == scores_from_scan.sort
392
+ end
393
+ end
394
+
395
+ def test_zscan_each_block_match
396
+ target_version "2.7.105" do
397
+ count = 1000
398
+ elements = []
399
+ count.times { |j| elements << j << "key:#{j}" }
400
+ r.zadd "zset", elements
401
+
402
+ scores_from_scan = []
403
+ r.zscan_each("zset", :match => "key:1??") do |member, score|
404
+ scores_from_scan << [member, score]
405
+ end
406
+ member_scores = r.zrange("zset", 0, -1, :with_scores => true)
407
+ filtered_members = member_scores.select{|k,s| k =~ /^key:1..$/}
408
+
409
+ assert filtered_members.sort == scores_from_scan.sort
410
+ end
411
+ end
412
+
413
+ end