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,133 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+ require "lint/value_types"
5
+
6
+ class TestCommandsOnValueTypes < Test::Unit::TestCase
7
+
8
+ include Helper::Client
9
+ include Lint::ValueTypes
10
+
11
+ def test_del
12
+ r.set "foo", "s1"
13
+ r.set "bar", "s2"
14
+ r.set "baz", "s3"
15
+
16
+ assert_equal ["bar", "baz", "foo"], r.keys("*").sort
17
+
18
+ assert_equal 1, r.del("foo")
19
+
20
+ assert_equal ["bar", "baz"], r.keys("*").sort
21
+
22
+ assert_equal 2, r.del("bar", "baz")
23
+
24
+ assert_equal [], r.keys("*").sort
25
+ end
26
+
27
+ def test_del_with_array_argument
28
+ r.set "foo", "s1"
29
+ r.set "bar", "s2"
30
+ r.set "baz", "s3"
31
+
32
+ assert_equal ["bar", "baz", "foo"], r.keys("*").sort
33
+
34
+ assert_equal 1, r.del(["foo"])
35
+
36
+ assert_equal ["bar", "baz"], r.keys("*").sort
37
+
38
+ assert_equal 2, r.del(["bar", "baz"])
39
+
40
+ assert_equal [], r.keys("*").sort
41
+ end
42
+
43
+ def test_randomkey
44
+ assert r.randomkey.to_s.empty?
45
+
46
+ r.set("foo", "s1")
47
+
48
+ assert_equal "foo", r.randomkey
49
+
50
+ r.set("bar", "s2")
51
+
52
+ 4.times do
53
+ assert ["foo", "bar"].include?(r.randomkey)
54
+ end
55
+ end
56
+
57
+ def test_rename
58
+ r.set("foo", "s1")
59
+ r.rename "foo", "bar"
60
+
61
+ assert_equal "s1", r.get("bar")
62
+ assert_equal nil, r.get("foo")
63
+ end
64
+
65
+ def test_renamenx
66
+ r.set("foo", "s1")
67
+ r.set("bar", "s2")
68
+
69
+ assert_equal false, r.renamenx("foo", "bar")
70
+
71
+ assert_equal "s1", r.get("foo")
72
+ assert_equal "s2", r.get("bar")
73
+ end
74
+
75
+ def test_dbsize
76
+ assert_equal 0, r.dbsize
77
+
78
+ r.set("foo", "s1")
79
+
80
+ assert_equal 1, r.dbsize
81
+ end
82
+
83
+ def test_flushdb
84
+ r.set("foo", "s1")
85
+ r.set("bar", "s2")
86
+
87
+ assert_equal 2, r.dbsize
88
+
89
+ r.flushdb
90
+
91
+ assert_equal 0, r.dbsize
92
+ end
93
+
94
+ def test_flushall
95
+ redis_mock(:flushall => lambda { "+FLUSHALL" }) do |redis|
96
+ assert_equal "FLUSHALL", redis.flushall
97
+ end
98
+ end
99
+
100
+ def test_migrate
101
+ redis_mock(:migrate => lambda { |*args| args }) do |redis|
102
+ options = { :host => "127.0.0.1", :port => 1234 }
103
+
104
+ ex = assert_raise(RuntimeError) do
105
+ redis.migrate("foo", options.reject { |key, _| key == :host })
106
+ end
107
+ assert ex.message =~ /host not specified/
108
+
109
+ ex = assert_raise(RuntimeError) do
110
+ redis.migrate("foo", options.reject { |key, _| key == :port })
111
+ end
112
+ assert ex.message =~ /port not specified/
113
+
114
+ default_db = redis.client.db.to_i
115
+ default_timeout = redis.client.timeout.to_i
116
+
117
+ # Test defaults
118
+ actual = redis.migrate("foo", options)
119
+ expected = ["127.0.0.1", "1234", "foo", default_db.to_s, default_timeout.to_s]
120
+ assert_equal expected, actual
121
+
122
+ # Test db override
123
+ actual = redis.migrate("foo", options.merge(:db => default_db + 1))
124
+ expected = ["127.0.0.1", "1234", "foo", (default_db + 1).to_s, default_timeout.to_s]
125
+ assert_equal expected, actual
126
+
127
+ # Test timeout override
128
+ actual = redis.migrate("foo", options.merge(:timeout => default_timeout + 1))
129
+ expected = ["127.0.0.1", "1234", "foo", default_db.to_s, (default_timeout + 1).to_s]
130
+ assert_equal expected, actual
131
+ end
132
+ end
133
+ end
@@ -0,0 +1,250 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+
5
+ class TestConnectionHandling < Test::Unit::TestCase
6
+
7
+ include Helper::Client
8
+
9
+ def test_auth
10
+ commands = {
11
+ :auth => lambda { |password| $auth = password; "+OK" },
12
+ :get => lambda { |key| $auth == "secret" ? "$3\r\nbar" : "$-1" },
13
+ }
14
+
15
+ redis_mock(commands, :password => "secret") do |redis|
16
+ assert_equal "bar", redis.get("foo")
17
+ end
18
+ end
19
+
20
+ def test_id
21
+ commands = {
22
+ :client => lambda { |cmd, name| $name = [cmd, name]; "+OK" },
23
+ :ping => lambda { "+PONG" },
24
+ }
25
+
26
+ redis_mock(commands, :id => "client-name") do |redis|
27
+ assert_equal "PONG", redis.ping
28
+ end
29
+
30
+ assert_equal ["setname","client-name"], $name
31
+ end
32
+
33
+ def test_ping
34
+ assert_equal "PONG", r.ping
35
+ end
36
+
37
+ def test_select
38
+ r.set "foo", "bar"
39
+
40
+ r.select 14
41
+ assert_equal nil, r.get("foo")
42
+
43
+ r.client.disconnect
44
+
45
+ assert_equal nil, r.get("foo")
46
+ end
47
+
48
+ def test_quit
49
+ r.quit
50
+
51
+ assert !r.client.connected?
52
+ end
53
+
54
+ def test_disconnect
55
+ quit = 0
56
+
57
+ commands = {
58
+ :quit => lambda do
59
+ quit += 1
60
+ "+OK"
61
+ end
62
+ }
63
+
64
+ redis_mock(commands) do |redis|
65
+ assert_equal 0, quit
66
+
67
+ redis.quit
68
+
69
+ assert_equal 1, quit
70
+
71
+ redis.ping
72
+
73
+ redis.disconnect!
74
+
75
+ assert_equal 1, quit
76
+
77
+ assert !redis.connected?
78
+ end
79
+ end
80
+
81
+ def test_shutdown
82
+ commands = {
83
+ :shutdown => lambda { :exit }
84
+ }
85
+
86
+ redis_mock(commands) do |redis|
87
+ # SHUTDOWN does not reply: test that it does not raise here.
88
+ assert_equal nil, redis.shutdown
89
+ end
90
+ end
91
+
92
+ def test_shutdown_with_error
93
+ connections = 0
94
+ commands = {
95
+ :select => lambda { |*_| connections += 1; "+OK\r\n" },
96
+ :connections => lambda { ":#{connections}\r\n" },
97
+ :shutdown => lambda { "-ERR could not shutdown\r\n" }
98
+ }
99
+
100
+ redis_mock(commands) do |redis|
101
+ connections = redis.connections
102
+
103
+ # SHUTDOWN replies with an error: test that it gets raised
104
+ assert_raise Redis::CommandError do
105
+ redis.shutdown
106
+ end
107
+
108
+ # The connection should remain in tact
109
+ assert_equal connections, redis.connections
110
+ end
111
+ end
112
+
113
+ def test_shutdown_from_pipeline
114
+ commands = {
115
+ :shutdown => lambda { :exit }
116
+ }
117
+
118
+ redis_mock(commands) do |redis|
119
+ result = redis.pipelined do
120
+ redis.shutdown
121
+ end
122
+
123
+ assert_equal nil, result
124
+ assert !redis.client.connected?
125
+ end
126
+ end
127
+
128
+ def test_shutdown_with_error_from_pipeline
129
+ connections = 0
130
+ commands = {
131
+ :select => lambda { |*_| connections += 1; "+OK\r\n" },
132
+ :connections => lambda { ":#{connections}\r\n" },
133
+ :shutdown => lambda { "-ERR could not shutdown\r\n" }
134
+ }
135
+
136
+ redis_mock(commands) do |redis|
137
+ connections = redis.connections
138
+
139
+ # SHUTDOWN replies with an error: test that it gets raised
140
+ assert_raise Redis::CommandError do
141
+ redis.pipelined do
142
+ redis.shutdown
143
+ end
144
+ end
145
+
146
+ # The connection should remain in tact
147
+ assert_equal connections, redis.connections
148
+ end
149
+ end
150
+
151
+ def test_shutdown_from_multi_exec
152
+ commands = {
153
+ :multi => lambda { "+OK\r\n" },
154
+ :shutdown => lambda { "+QUEUED\r\n" },
155
+ :exec => lambda { :exit }
156
+ }
157
+
158
+ redis_mock(commands) do |redis|
159
+ result = redis.multi do
160
+ redis.shutdown
161
+ end
162
+
163
+ assert_equal nil, result
164
+ assert !redis.client.connected?
165
+ end
166
+ end
167
+
168
+ def test_shutdown_with_error_from_multi_exec
169
+ connections = 0
170
+ commands = {
171
+ :select => lambda { |*_| connections += 1; "+OK\r\n" },
172
+ :connections => lambda { ":#{connections}\r\n" },
173
+ :multi => lambda { "+OK\r\n" },
174
+ :shutdown => lambda { "+QUEUED\r\n" },
175
+ :exec => lambda { "*1\r\n-ERR could not shutdown\r\n" }
176
+ }
177
+
178
+ redis_mock(commands) do |redis|
179
+ connections = redis.connections
180
+
181
+ # SHUTDOWN replies with an error: test that it gets returned
182
+ # We should test for Redis::CommandError here, but hiredis doesn't yet do
183
+ # custom error classes.
184
+ err = nil
185
+
186
+ begin
187
+ redis.multi { redis.shutdown }
188
+ rescue => err
189
+ end
190
+
191
+ assert err.kind_of?(StandardError)
192
+
193
+ # The connection should remain intact
194
+ assert_equal connections, redis.connections
195
+ end
196
+ end
197
+
198
+ def test_slaveof
199
+ redis_mock(:slaveof => lambda { |host, port| "+SLAVEOF #{host} #{port}" }) do |redis|
200
+ assert_equal "SLAVEOF somehost 6381", redis.slaveof("somehost", 6381)
201
+ end
202
+ end
203
+
204
+ def test_bgrewriteaof
205
+ redis_mock(:bgrewriteaof => lambda { "+BGREWRITEAOF" }) do |redis|
206
+ assert_equal "BGREWRITEAOF", redis.bgrewriteaof
207
+ end
208
+ end
209
+
210
+ def test_config_get
211
+ assert r.config(:get, "*")["timeout"] != nil
212
+
213
+ config = r.config(:get, "timeout")
214
+ assert_equal ["timeout"], config.keys
215
+ assert config.values.compact.size > 0
216
+ end
217
+
218
+ def test_config_set
219
+ begin
220
+ assert_equal "OK", r.config(:set, "timeout", 200)
221
+ assert_equal "200", r.config(:get, "*")["timeout"]
222
+
223
+ assert_equal "OK", r.config(:set, "timeout", 100)
224
+ assert_equal "100", r.config(:get, "*")["timeout"]
225
+ ensure
226
+ r.config :set, "timeout", 300
227
+ end
228
+ end
229
+
230
+ driver(:ruby, :hiredis) do
231
+ def test_consistency_on_multithreaded_env
232
+ t = nil
233
+
234
+ commands = {
235
+ :set => lambda { |key, value| t.kill; "+OK\r\n" },
236
+ :incr => lambda { |key| ":1\r\n" },
237
+ }
238
+
239
+ redis_mock(commands) do |redis|
240
+ t = Thread.new do
241
+ redis.set("foo", "bar")
242
+ end
243
+
244
+ t.join
245
+
246
+ assert_equal 1, redis.incr("baz")
247
+ end
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,46 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+ require "lint/blocking_commands"
5
+
6
+ class TestDistributedBlockingCommands < Test::Unit::TestCase
7
+
8
+ include Helper::Distributed
9
+ include Lint::BlockingCommands
10
+
11
+ def test_blpop_raises
12
+ assert_raises(Redis::Distributed::CannotDistribute) do
13
+ r.blpop(["foo", "bar"])
14
+ end
15
+ end
16
+
17
+ def test_blpop_raises_with_old_prototype
18
+ assert_raises(Redis::Distributed::CannotDistribute) do
19
+ r.blpop("foo", "bar", 0)
20
+ end
21
+ end
22
+
23
+ def test_brpop_raises
24
+ assert_raises(Redis::Distributed::CannotDistribute) do
25
+ r.brpop(["foo", "bar"])
26
+ end
27
+ end
28
+
29
+ def test_brpop_raises_with_old_prototype
30
+ assert_raises(Redis::Distributed::CannotDistribute) do
31
+ r.brpop("foo", "bar", 0)
32
+ end
33
+ end
34
+
35
+ def test_brpoplpush_raises
36
+ assert_raises(Redis::Distributed::CannotDistribute) do
37
+ r.brpoplpush("foo", "bar")
38
+ end
39
+ end
40
+
41
+ def test_brpoplpush_raises_with_old_prototype
42
+ assert_raises(Redis::Distributed::CannotDistribute) do
43
+ r.brpoplpush("foo", "bar", 0)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,10 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+ require "lint/hashes"
5
+
6
+ class TestDistributedCommandsOnHashes < Test::Unit::TestCase
7
+
8
+ include Helper::Distributed
9
+ include Lint::Hashes
10
+ end
@@ -0,0 +1,33 @@
1
+ # encoding: UTF-8
2
+
3
+ require File.expand_path("helper", File.dirname(__FILE__))
4
+ require "lint/hyper_log_log"
5
+
6
+ class TestDistributedCommandsOnHyperLogLog < Test::Unit::TestCase
7
+
8
+ include Helper::Distributed
9
+ include Lint::HyperLogLog
10
+
11
+ def test_pfmerge
12
+ target_version "2.8.9" do
13
+ assert_raise Redis::Distributed::CannotDistribute do
14
+ r.pfadd "foo", "s1"
15
+ r.pfadd "bar", "s2"
16
+
17
+ assert r.pfmerge("res", "foo", "bar")
18
+ end
19
+ end
20
+ end
21
+
22
+ def test_pfcount_multiple_keys_diff_nodes
23
+ target_version "2.8.9" do
24
+ assert_raise Redis::Distributed::CannotDistribute do
25
+ r.pfadd "foo", "s1"
26
+ r.pfadd "bar", "s2"
27
+
28
+ assert r.pfcount("res", "foo", "bar")
29
+ end
30
+ end
31
+ end
32
+
33
+ end