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