discourse-redis 3.2.2

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 (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