lunar 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. data/.gitignore +2 -1
  2. data/LICENSE +1 -1
  3. data/README.markdown +116 -0
  4. data/Rakefile +6 -5
  5. data/VERSION +1 -1
  6. data/lib/lunar.rb +112 -24
  7. data/lib/lunar/connection.rb +51 -0
  8. data/lib/lunar/fuzzy_matches.rb +24 -0
  9. data/lib/lunar/fuzzy_word.rb +2 -2
  10. data/lib/lunar/index.rb +200 -94
  11. data/lib/lunar/keyword_matches.rb +32 -0
  12. data/lib/lunar/lunar_nest.rb +19 -0
  13. data/lib/lunar/range_matches.rb +28 -0
  14. data/lib/lunar/result_set.rb +85 -28
  15. data/lib/lunar/scoring.rb +4 -2
  16. data/lib/lunar/stopwords.rb +15 -0
  17. data/lib/lunar/words.rb +6 -3
  18. data/lunar.gemspec +31 -60
  19. data/test/helper.rb +4 -5
  20. data/test/test_fuzzy_indexing.rb +105 -0
  21. data/test/test_index.rb +150 -0
  22. data/test/test_lunar.rb +178 -1
  23. data/test/test_lunar_fuzzy_word.rb +4 -4
  24. data/test/test_lunar_nest.rb +46 -0
  25. data/test/{test_lunar_scoring.rb → test_scoring.rb} +5 -5
  26. metadata +72 -68
  27. data/.document +0 -5
  28. data/DATA +0 -41
  29. data/README.md +0 -80
  30. data/examples/ohm.rb +0 -40
  31. data/lib/lunar/search.rb +0 -68
  32. data/lib/lunar/sets.rb +0 -86
  33. data/test/test_lunar_fuzzy.rb +0 -118
  34. data/test/test_lunar_index.rb +0 -191
  35. data/test/test_lunar_search.rb +0 -261
  36. data/test/test_sets.rb +0 -48
  37. data/vendor/nest/nest.rb +0 -7
  38. data/vendor/redis/.gitignore +0 -9
  39. data/vendor/redis/LICENSE +0 -20
  40. data/vendor/redis/README.markdown +0 -120
  41. data/vendor/redis/Rakefile +0 -75
  42. data/vendor/redis/benchmarking/logging.rb +0 -62
  43. data/vendor/redis/benchmarking/pipeline.rb +0 -44
  44. data/vendor/redis/benchmarking/speed.rb +0 -21
  45. data/vendor/redis/benchmarking/suite.rb +0 -24
  46. data/vendor/redis/benchmarking/worker.rb +0 -71
  47. data/vendor/redis/bin/distredis +0 -33
  48. data/vendor/redis/examples/basic.rb +0 -15
  49. data/vendor/redis/examples/dist_redis.rb +0 -43
  50. data/vendor/redis/examples/incr-decr.rb +0 -17
  51. data/vendor/redis/examples/list.rb +0 -26
  52. data/vendor/redis/examples/pubsub.rb +0 -25
  53. data/vendor/redis/examples/sets.rb +0 -36
  54. data/vendor/redis/lib/edis.rb +0 -3
  55. data/vendor/redis/lib/redis.rb +0 -496
  56. data/vendor/redis/lib/redis/client.rb +0 -265
  57. data/vendor/redis/lib/redis/dist_redis.rb +0 -118
  58. data/vendor/redis/lib/redis/distributed.rb +0 -460
  59. data/vendor/redis/lib/redis/hash_ring.rb +0 -131
  60. data/vendor/redis/lib/redis/pipeline.rb +0 -13
  61. data/vendor/redis/lib/redis/raketasks.rb +0 -1
  62. data/vendor/redis/lib/redis/subscribe.rb +0 -79
  63. data/vendor/redis/profile.rb +0 -22
  64. data/vendor/redis/tasks/redis.tasks.rb +0 -140
  65. data/vendor/redis/test/db/.gitignore +0 -1
  66. data/vendor/redis/test/distributed_test.rb +0 -1131
  67. data/vendor/redis/test/redis_test.rb +0 -1134
  68. data/vendor/redis/test/test.conf +0 -8
  69. data/vendor/redis/test/test_helper.rb +0 -113
@@ -1,131 +0,0 @@
1
- require 'zlib'
2
-
3
- class Redis
4
- class HashRing
5
-
6
- POINTS_PER_SERVER = 160 # this is the default in libmemcached
7
-
8
- attr_reader :ring, :sorted_keys, :replicas, :nodes
9
-
10
- # nodes is a list of objects that have a proper to_s representation.
11
- # replicas indicates how many virtual points should be used pr. node,
12
- # replicas are required to improve the distribution.
13
- def initialize(nodes=[], replicas=POINTS_PER_SERVER)
14
- @replicas = replicas
15
- @ring = {}
16
- @nodes = []
17
- @sorted_keys = []
18
- nodes.each do |node|
19
- add_node(node)
20
- end
21
- end
22
-
23
- # Adds a `node` to the hash ring (including a number of replicas).
24
- def add_node(node)
25
- @nodes << node
26
- @replicas.times do |i|
27
- key = Zlib.crc32("#{node.id}:#{i}")
28
- @ring[key] = node
29
- @sorted_keys << key
30
- end
31
- @sorted_keys.sort!
32
- end
33
-
34
- def remove_node(node)
35
- @nodes.reject!{|n| n.id == node.id}
36
- @replicas.times do |i|
37
- key = Zlib.crc32("#{node.id}:#{i}")
38
- @ring.delete(key)
39
- @sorted_keys.reject! {|k| k == key}
40
- end
41
- end
42
-
43
- # get the node in the hash ring for this key
44
- def get_node(key)
45
- get_node_pos(key)[0]
46
- end
47
-
48
- def get_node_pos(key)
49
- return [nil,nil] if @ring.size == 0
50
- crc = Zlib.crc32(key)
51
- idx = HashRing.binary_search(@sorted_keys, crc)
52
- return [@ring[@sorted_keys[idx]], idx]
53
- end
54
-
55
- def iter_nodes(key)
56
- return [nil,nil] if @ring.size == 0
57
- node, pos = get_node_pos(key)
58
- @sorted_keys[pos..-1].each do |k|
59
- yield @ring[k]
60
- end
61
- end
62
-
63
- class << self
64
-
65
- # gem install RubyInline to use this code
66
- # Native extension to perform the binary search within the hashring.
67
- # There's a pure ruby version below so this is purely optional
68
- # for performance. In testing 20k gets and sets, the native
69
- # binary search shaved about 12% off the runtime (9sec -> 8sec).
70
- begin
71
- require 'inline'
72
- inline do |builder|
73
- builder.c <<-EOM
74
- int binary_search(VALUE ary, unsigned int r) {
75
- int upper = RARRAY_LEN(ary) - 1;
76
- int lower = 0;
77
- int idx = 0;
78
-
79
- while (lower <= upper) {
80
- idx = (lower + upper) / 2;
81
-
82
- VALUE continuumValue = RARRAY_PTR(ary)[idx];
83
- unsigned int l = NUM2UINT(continuumValue);
84
- if (l == r) {
85
- return idx;
86
- }
87
- else if (l > r) {
88
- upper = idx - 1;
89
- }
90
- else {
91
- lower = idx + 1;
92
- }
93
- }
94
- if (upper < 0) {
95
- upper = RARRAY_LEN(ary) - 1;
96
- }
97
- return upper;
98
- }
99
- EOM
100
- end
101
- rescue Exception => e
102
- # Find the closest index in HashRing with value <= the given value
103
- def binary_search(ary, value, &block)
104
- upper = ary.size - 1
105
- lower = 0
106
- idx = 0
107
-
108
- while(lower <= upper) do
109
- idx = (lower + upper) / 2
110
- comp = ary[idx] <=> value
111
-
112
- if comp == 0
113
- return idx
114
- elsif comp > 0
115
- upper = idx - 1
116
- else
117
- lower = idx + 1
118
- end
119
- end
120
-
121
- if upper < 0
122
- upper = ary.size - 1
123
- end
124
- return upper
125
- end
126
-
127
- end
128
- end
129
-
130
- end
131
- end
@@ -1,13 +0,0 @@
1
- class Redis
2
- class Pipeline
3
- attr :commands
4
-
5
- def initialize
6
- @commands = []
7
- end
8
-
9
- def call(*args)
10
- @commands << args
11
- end
12
- end
13
- end
@@ -1 +0,0 @@
1
- require File.dirname(__FILE__) + "/../../tasks/redis.tasks"
@@ -1,79 +0,0 @@
1
- class Redis
2
- class SubscribedClient
3
- def initialize(client)
4
- @client = client
5
- end
6
-
7
- def call(*args)
8
- @client.process(args)
9
- end
10
-
11
- def subscribe(*channels, &block)
12
- subscription("subscribe", "unsubscribe", channels, block)
13
- end
14
-
15
- def psubscribe(*channels, &block)
16
- subscription("psubscribe", "punsubscribe", channels, block)
17
- end
18
-
19
- def unsubscribe(*channels)
20
- call(:unsubscribe, *channels)
21
- end
22
-
23
- def punsubscribe(*channels)
24
- call(:punsubscribe, *channels)
25
- end
26
-
27
- protected
28
-
29
- def subscription(start, stop, channels, block)
30
- sub = Subscription.new(&block)
31
-
32
- begin
33
- @client.call_loop(start, *channels) do |line|
34
- type, *rest = line
35
- sub.callbacks[type].call(*rest)
36
- break if type == stop && rest.last == 0
37
- end
38
- ensure
39
- send(stop)
40
- end
41
- end
42
- end
43
-
44
- class Subscription
45
- attr :callbacks
46
-
47
- def initialize
48
- @callbacks = Hash.new do |hash, key|
49
- hash[key] = lambda { |*_| }
50
- end
51
-
52
- yield(self)
53
- end
54
-
55
- def subscribe(&block)
56
- @callbacks["subscribe"] = block
57
- end
58
-
59
- def unsubscribe(&block)
60
- @callbacks["unsubscribe"] = block
61
- end
62
-
63
- def message(&block)
64
- @callbacks["message"] = block
65
- end
66
-
67
- def psubscribe(&block)
68
- @callbacks["psubscribe"] = block
69
- end
70
-
71
- def punsubscribe(&block)
72
- @callbacks["punsubscribe"] = block
73
- end
74
-
75
- def pmessage(&block)
76
- @callbacks["pmessage"] = block
77
- end
78
- end
79
- end
@@ -1,22 +0,0 @@
1
- require 'rubygems'
2
- require 'ruby-prof'
3
- require "#{File.dirname(__FILE__)}/lib/redis"
4
-
5
-
6
- mode = ARGV.shift || 'process_time'
7
- n = (ARGV.shift || 200).to_i
8
-
9
- r = Redis.new
10
- RubyProf.measure_mode = RubyProf.const_get(mode.upcase)
11
- RubyProf.start
12
-
13
- n.times do |i|
14
- key = "foo#{i}"
15
- r[key] = key * 10
16
- r[key]
17
- end
18
-
19
- results = RubyProf.stop
20
- File.open("profile.#{mode}", 'w') do |out|
21
- RubyProf::CallTreePrinter.new(results).print(out)
22
- end
@@ -1,140 +0,0 @@
1
- # Inspired by rabbitmq.rake the Redbox project at http://github.com/rick/redbox/tree/master
2
- require 'rake'
3
- require 'fileutils'
4
- require 'open-uri'
5
-
6
- class RedisRunner
7
-
8
- def self.redisdir
9
- "/tmp/redis/"
10
- end
11
-
12
- def self.redisconfdir
13
- '/etc/redis.conf'
14
- end
15
-
16
- def self.dtach_socket
17
- '/tmp/redis.dtach'
18
- end
19
-
20
- # Just check for existance of dtach socket
21
- def self.running?
22
- File.exists? dtach_socket
23
- end
24
-
25
- def self.start
26
- puts 'Detach with Ctrl+\ Re-attach with rake redis:attach'
27
- sleep 3
28
- exec "dtach -A #{dtach_socket} redis-server #{redisconfdir}"
29
- end
30
-
31
- def self.start_detached
32
- system "dtach -n #{dtach_socket} redis-server #{redisconfdir}"
33
- end
34
-
35
- def self.attach
36
- exec "dtach -a #{dtach_socket}"
37
- end
38
-
39
- def self.stop
40
- system 'echo "SHUTDOWN" | nc localhost 6379'
41
- end
42
-
43
- end
44
-
45
- namespace :redis do
46
-
47
- desc 'About redis'
48
- task :about do
49
- puts "\nSee http://code.google.com/p/redis/ for information about redis.\n\n"
50
- end
51
-
52
- desc 'Start redis'
53
- task :start do
54
- RedisRunner.start
55
- end
56
-
57
- desc 'Stop redis'
58
- task :stop do
59
- RedisRunner.stop
60
- end
61
-
62
- desc 'Restart redis'
63
- task :restart do
64
- RedisRunner.stop
65
- RedisRunner.start
66
- end
67
-
68
- desc 'Attach to redis dtach socket'
69
- task :attach do
70
- RedisRunner.attach
71
- end
72
-
73
- desc 'Install the lastest verison of Redis from Github (requires git, duh)'
74
- task :install => [:about, :download, :make] do
75
- %w(redis-benchmark redis-cli redis-server).each do |bin|
76
- sh "sudo cp /tmp/redis/#{bin} /usr/bin/"
77
- end
78
-
79
- puts "Installed redis-benchmark, redis-cli and redis-server to /usr/bin/"
80
-
81
- unless File.exists?('/etc/redis.conf')
82
- sh 'sudo cp /tmp/redis/redis.conf /etc/'
83
- puts "Installed redis.conf to /etc/ \n You should look at this file!"
84
- end
85
- end
86
-
87
- task :make do
88
- sh "cd #{RedisRunner.redisdir} && make clean"
89
- sh "cd #{RedisRunner.redisdir} && make"
90
- end
91
-
92
- desc "Download package"
93
- task :download do
94
- sh 'rm -rf /tmp/redis/' if File.exists?("#{RedisRunner.redisdir}/.svn")
95
- sh 'git clone git://github.com/antirez/redis.git /tmp/redis' unless File.exists?(RedisRunner.redisdir)
96
-
97
- if File.exists?("#{RedisRunner.redisdir}/.git")
98
- arguments = ENV['COMMIT'].nil? ? "pull" : "reset --hard #{ENV['COMMIT']}"
99
- sh "cd #{RedisRunner.redisdir} && git #{arguments}"
100
- end
101
- end
102
-
103
- desc "Open an IRb session"
104
- task :console do
105
- RedisRunner.start_detached
106
- system "irb -I lib -I extra -r redis.rb"
107
- RedisRunner.stop
108
- end
109
- end
110
-
111
- namespace :dtach do
112
-
113
- desc 'About dtach'
114
- task :about do
115
- puts "\nSee http://dtach.sourceforge.net/ for information about dtach.\n\n"
116
- end
117
-
118
- desc 'Install dtach 0.8 from source'
119
- task :install => [:about] do
120
-
121
- Dir.chdir('/tmp/')
122
- unless File.exists?('/tmp/dtach-0.8.tar.gz')
123
- require 'net/http'
124
-
125
- url = 'http://downloads.sourceforge.net/project/dtach/dtach/0.8/dtach-0.8.tar.gz'
126
- open('/tmp/dtach-0.8.tar.gz', 'wb') do |file| file.write(open(url).read) end
127
- end
128
-
129
- unless File.directory?('/tmp/dtach-0.8')
130
- system('tar xzf dtach-0.8.tar.gz')
131
- end
132
-
133
- Dir.chdir('/tmp/dtach-0.8/')
134
- sh 'cd /tmp/dtach-0.8/ && ./configure && make'
135
- sh 'sudo cp /tmp/dtach-0.8/dtach /usr/bin/'
136
-
137
- puts 'Dtach successfully installed to /usr/bin.'
138
- end
139
- end
140
-
@@ -1 +0,0 @@
1
- redis.pid
@@ -1,1131 +0,0 @@
1
- require File.join(File.dirname(__FILE__), "test_helper")
2
-
3
- require "redis/distributed"
4
-
5
- class RedisDistributedTest < Test::Unit::TestCase
6
- NODES = ["redis://127.0.0.1:6379/15"]
7
-
8
- setup do
9
- @log = StringIO.new
10
- @r = Redis::Distributed.new NODES, :logger => ::Logger.new(@log)
11
- ensure_redis_running(@r)
12
- @r.flushdb
13
- end
14
-
15
- context "Internals" do
16
- test "Logger" do
17
- @r.ping
18
-
19
- assert_match(/Redis >> PING/, @log.string)
20
- end
21
-
22
- test "Recovers from failed commands" do
23
- # See http://github.com/ezmobius/redis-rb/issues#issue/28
24
-
25
- assert_raises ArgumentError do
26
- @r.srem "foo"
27
- end
28
-
29
- assert_nothing_raised do
30
- @r.info
31
- end
32
- end
33
- end
34
-
35
- context "Connection handling" do
36
- test "PING" do
37
- assert_equal ["PONG"], @r.ping
38
- end
39
-
40
- test "SELECT" do
41
- @r.set "foo", "bar"
42
-
43
- @r.select 14
44
- assert_equal nil, @r.get("foo")
45
-
46
- @r.select 15
47
-
48
- assert_equal "bar", @r.get("foo")
49
- end
50
- end
51
-
52
- context "Commands operating on all the kind of values" do
53
- test "EXISTS" do
54
- assert_equal false, @r.exists("foo")
55
-
56
- @r.set("foo", "s1")
57
-
58
- assert_equal true, @r.exists("foo")
59
- end
60
-
61
- test "DEL" do
62
- @r.set "foo", "s1"
63
- @r.set "bar", "s2"
64
- @r.set "baz", "s3"
65
-
66
- assert_equal ["bar", "baz", "foo"], @r.keys("*").sort
67
-
68
- @r.del "foo"
69
-
70
- assert_equal ["bar", "baz"], @r.keys("*").sort
71
-
72
- @r.del "bar", "baz"
73
-
74
- assert_equal [], @r.keys("*").sort
75
- end
76
-
77
- test "TYPE" do
78
- assert_equal "none", @r.type("foo")
79
-
80
- @r.set("foo", "s1")
81
-
82
- assert_equal "string", @r.type("foo")
83
- end
84
-
85
- test "KEYS" do
86
- @r.set("f", "s1")
87
- @r.set("fo", "s2")
88
- @r.set("foo", "s3")
89
-
90
- assert_equal ["f","fo", "foo"], @r.keys("f*").sort
91
- end
92
-
93
- test "RANDOMKEY" do
94
- assert_raises Redis::Distributed::CannotDistribute do
95
- @r.randomkey
96
- end
97
- end
98
-
99
- test "RENAME" do
100
- assert_raises Redis::Distributed::CannotDistribute do
101
- @r.set("foo", "s1")
102
- @r.rename "foo", "bar"
103
- end
104
-
105
- assert_equal "s1", @r.get("foo")
106
- assert_equal nil, @r.get("bar")
107
- end
108
-
109
- test "RENAMENX" do
110
- assert_raises Redis::Distributed::CannotDistribute do
111
- @r.set("foo", "s1")
112
- @r.rename "foo", "bar"
113
- end
114
-
115
- assert_equal "s1", @r.get("foo")
116
- assert_equal nil, @r.get("bar")
117
- end
118
-
119
- test "DBSIZE" do
120
- assert_equal [0], @r.dbsize
121
-
122
- @r.set("foo", "s1")
123
-
124
- assert_equal [1], @r.dbsize
125
- end
126
-
127
- test "EXPIRE" do
128
- @r.set("foo", "s1")
129
- @r.expire("foo", 1)
130
-
131
- assert_equal "s1", @r.get("foo")
132
-
133
- sleep 2
134
-
135
- assert_equal nil, @r.get("foo")
136
- end
137
-
138
- test "EXPIREAT" do
139
- @r.set("foo", "s1")
140
- @r.expireat("foo", Time.now.to_i + 1)
141
-
142
- assert_equal "s1", @r.get("foo")
143
-
144
- sleep 2
145
-
146
- assert_equal nil, @r.get("foo")
147
- end
148
-
149
- test "TTL" do
150
- @r.set("foo", "s1")
151
- @r.expire("foo", 1)
152
-
153
- assert_equal 1, @r.ttl("foo")
154
- end
155
-
156
- test "MOVE"
157
-
158
- test "FLUSHDB" do
159
- @r.set("foo", "s1")
160
- @r.set("bar", "s2")
161
-
162
- assert_equal [2], @r.dbsize
163
-
164
- @r.flushdb
165
-
166
- assert_equal [0], @r.dbsize
167
- end
168
- end
169
-
170
- context "Commands requiring clustering" do
171
- test "RENAME" do
172
- @r.set("{qux}foo", "s1")
173
- @r.rename "{qux}foo", "{qux}bar"
174
-
175
- assert_equal "s1", @r.get("{qux}bar")
176
- assert_equal nil, @r.get("{qux}foo")
177
- end
178
-
179
- test "RENAMENX" do
180
- @r.set("{qux}foo", "s1")
181
- @r.set("{qux}bar", "s2")
182
-
183
- assert_equal false, @r.renamenx("{qux}foo", "{qux}bar")
184
-
185
- assert_equal "s1", @r.get("{qux}foo")
186
- assert_equal "s2", @r.get("{qux}bar")
187
- end
188
-
189
- test "RPOPLPUSH" do
190
- @r.rpush "{qux}foo", "s1"
191
- @r.rpush "{qux}foo", "s2"
192
-
193
- assert_equal "s2", @r.rpoplpush("{qux}foo", "{qux}bar")
194
- assert_equal ["s2"], @r.lrange("{qux}bar", 0, -1)
195
- assert_equal "s1", @r.rpoplpush("{qux}foo", "{qux}bar")
196
- assert_equal ["s1", "s2"], @r.lrange("{qux}bar", 0, -1)
197
- end
198
-
199
- test "SMOVE" do
200
- @r.sadd "{qux}foo", "s1"
201
- @r.sadd "{qux}bar", "s2"
202
-
203
- assert @r.smove("{qux}foo", "{qux}bar", "s1")
204
- assert @r.sismember("{qux}bar", "s1")
205
- end
206
-
207
- test "SINTER" do
208
- @r.sadd "{qux}foo", "s1"
209
- @r.sadd "{qux}foo", "s2"
210
- @r.sadd "{qux}bar", "s2"
211
-
212
- assert_equal ["s2"], @r.sinter("{qux}foo", "{qux}bar")
213
- end
214
-
215
- test "SINTERSTORE" do
216
- @r.sadd "{qux}foo", "s1"
217
- @r.sadd "{qux}foo", "s2"
218
- @r.sadd "{qux}bar", "s2"
219
-
220
- @r.sinterstore("{qux}baz", "{qux}foo", "{qux}bar")
221
-
222
- assert_equal ["s2"], @r.smembers("{qux}baz")
223
- end
224
-
225
- test "SUNION" do
226
- @r.sadd "{qux}foo", "s1"
227
- @r.sadd "{qux}foo", "s2"
228
- @r.sadd "{qux}bar", "s2"
229
- @r.sadd "{qux}bar", "s3"
230
-
231
- assert_equal ["s1", "s2", "s3"], @r.sunion("{qux}foo", "{qux}bar").sort
232
- end
233
-
234
- test "SUNIONSTORE" do
235
- @r.sadd "{qux}foo", "s1"
236
- @r.sadd "{qux}foo", "s2"
237
- @r.sadd "{qux}bar", "s2"
238
- @r.sadd "{qux}bar", "s3"
239
-
240
- @r.sunionstore("{qux}baz", "{qux}foo", "{qux}bar")
241
-
242
- assert_equal ["s1", "s2", "s3"], @r.smembers("{qux}baz").sort
243
- end
244
-
245
- test "SDIFF" do
246
- @r.sadd "{qux}foo", "s1"
247
- @r.sadd "{qux}foo", "s2"
248
- @r.sadd "{qux}bar", "s2"
249
- @r.sadd "{qux}bar", "s3"
250
-
251
- assert_equal ["s1"], @r.sdiff("{qux}foo", "{qux}bar")
252
- assert_equal ["s3"], @r.sdiff("{qux}bar", "{qux}foo")
253
- end
254
-
255
- test "SDIFFSTORE" do
256
- @r.sadd "{qux}foo", "s1"
257
- @r.sadd "{qux}foo", "s2"
258
- @r.sadd "{qux}bar", "s2"
259
- @r.sadd "{qux}bar", "s3"
260
-
261
- @r.sdiffstore("{qux}baz", "{qux}foo", "{qux}bar")
262
-
263
- assert_equal ["s1"], @r.smembers("{qux}baz")
264
- end
265
-
266
- test "SORT" do
267
- @r.set("foo:1", "s1")
268
- @r.set("foo:2", "s2")
269
-
270
- @r.rpush("{qux}bar", "1")
271
- @r.rpush("{qux}bar", "2")
272
-
273
- assert_equal ["s1"], @r.sort("{qux}bar", :get => "foo:*", :limit => [0, 1])
274
- assert_equal ["s2"], @r.sort("{qux}bar", :get => "foo:*", :limit => [0, 1], :order => "desc alpha")
275
- end
276
-
277
- test "SORT with an array of GETs" do
278
- @r.set("foo:1:a", "s1a")
279
- @r.set("foo:1:b", "s1b")
280
-
281
- @r.set("foo:2:a", "s2a")
282
- @r.set("foo:2:b", "s2b")
283
-
284
- @r.rpush("{qux}bar", "1")
285
- @r.rpush("{qux}bar", "2")
286
-
287
- assert_equal ["s1a", "s1b"], @r.sort("{qux}bar", :get => ["foo:*:a", "foo:*:b"], :limit => [0, 1])
288
- assert_equal ["s2a", "s2b"], @r.sort("{qux}bar", :get => ["foo:*:a", "foo:*:b"], :limit => [0, 1], :order => "desc alpha")
289
- end
290
-
291
- test "SORT with STORE" do
292
- @r.set("foo:1", "s1")
293
- @r.set("foo:2", "s2")
294
-
295
- @r.rpush("{qux}bar", "1")
296
- @r.rpush("{qux}bar", "2")
297
-
298
- @r.sort("{qux}bar", :get => "foo:*", :store => "{qux}baz")
299
- assert_equal ["s1", "s2"], @r.lrange("{qux}baz", 0, -1)
300
- end
301
- end
302
-
303
- context "Commands operating on string values" do
304
- test "SET and GET" do
305
- @r.set("foo", "s1")
306
-
307
- assert_equal "s1", @r.get("foo")
308
- end
309
-
310
- test "SET and GET with brackets" do
311
- @r["foo"] = "s1"
312
-
313
- assert_equal "s1", @r["foo"]
314
- end
315
-
316
- test "SET and GET with newline characters" do
317
- @r.set("foo", "1\n")
318
-
319
- assert_equal "1\n", @r.get("foo")
320
- end
321
-
322
- test "SET and GET with ASCII characters" do
323
- (0..255).each do |i|
324
- str = "#{i.chr}---#{i.chr}"
325
- @r.set("foo", str)
326
-
327
- assert_equal str, @r.get("foo")
328
- end
329
- end
330
-
331
- test "SETEX" do
332
- @r.setex("foo", 1, "s1")
333
-
334
- assert_equal "s1", @r.get("foo")
335
-
336
- sleep 2
337
-
338
- assert_equal nil, @r.get("foo")
339
- end
340
-
341
- test "GETSET" do
342
- @r.set("foo", "bar")
343
-
344
- assert_equal "bar", @r.getset("foo", "baz")
345
- assert_equal "baz", @r.get("foo")
346
- end
347
-
348
- test "MGET" do
349
- assert_raises Redis::Distributed::CannotDistribute do
350
- @r.mget("foo", "bar")
351
- end
352
- end
353
-
354
- test "MGET mapped" do
355
- assert_raises Redis::Distributed::CannotDistribute do
356
- @r.mapped_mget("foo", "bar")
357
- end
358
- end
359
-
360
- test "SETNX" do
361
- @r.set("foo", "s1")
362
-
363
- assert_equal "s1", @r.get("foo")
364
-
365
- @r.setnx("foo", "s2")
366
-
367
- assert_equal "s1", @r.get("foo")
368
- end
369
-
370
- test "MSET" do
371
- assert_raises Redis::Distributed::CannotDistribute do
372
- @r.mset(:foo, "s1", :bar, "s2")
373
- end
374
- end
375
-
376
- test "MSET mapped" do
377
- assert_raises Redis::Distributed::CannotDistribute do
378
- @r.mapped_mset(:foo => "s1", :bar => "s2")
379
- end
380
- end
381
-
382
- test "MSETNX" do
383
- assert_raises Redis::Distributed::CannotDistribute do
384
- @r.set("foo", "s1")
385
- @r.msetnx(:foo, "s2", :bar, "s3")
386
- end
387
- end
388
-
389
- test "MSETNX mapped" do
390
- assert_raises Redis::Distributed::CannotDistribute do
391
- @r.set("foo", "s1")
392
- @r.mapped_msetnx(:foo => "s2", :bar => "s3")
393
- end
394
- end
395
-
396
- test "INCR" do
397
- assert_equal 1, @r.incr("foo")
398
- assert_equal 2, @r.incr("foo")
399
- assert_equal 3, @r.incr("foo")
400
- end
401
-
402
- test "INCRBY" do
403
- assert_equal 1, @r.incrby("foo", 1)
404
- assert_equal 3, @r.incrby("foo", 2)
405
- assert_equal 6, @r.incrby("foo", 3)
406
- end
407
-
408
- test "DECR" do
409
- @r.set("foo", 3)
410
-
411
- assert_equal 2, @r.decr("foo")
412
- assert_equal 1, @r.decr("foo")
413
- assert_equal 0, @r.decr("foo")
414
- end
415
-
416
- test "DECRBY" do
417
- @r.set("foo", 6)
418
-
419
- assert_equal 3, @r.decrby("foo", 3)
420
- assert_equal 1, @r.decrby("foo", 2)
421
- assert_equal 0, @r.decrby("foo", 1)
422
- end
423
- end
424
-
425
- context "Commands operating on lists" do
426
- test "RPUSH" do
427
- @r.rpush "foo", "s1"
428
- @r.rpush "foo", "s2"
429
-
430
- assert_equal 2, @r.llen("foo")
431
- assert_equal "s2", @r.rpop("foo")
432
- end
433
-
434
- test "LPUSH" do
435
- @r.lpush "foo", "s1"
436
- @r.lpush "foo", "s2"
437
-
438
- assert_equal 2, @r.llen("foo")
439
- assert_equal "s2", @r.lpop("foo")
440
- end
441
-
442
- test "LLEN" do
443
- @r.rpush "foo", "s1"
444
- @r.rpush "foo", "s2"
445
-
446
- assert_equal 2, @r.llen("foo")
447
- end
448
-
449
- test "LRANGE" do
450
- @r.rpush "foo", "s1"
451
- @r.rpush "foo", "s2"
452
- @r.rpush "foo", "s3"
453
-
454
- assert_equal ["s2", "s3"], @r.lrange("foo", 1, -1)
455
- assert_equal ["s1", "s2"], @r.lrange("foo", 0, 1)
456
- end
457
-
458
- test "LTRIM" do
459
- @r.rpush "foo", "s1"
460
- @r.rpush "foo", "s2"
461
- @r.rpush "foo", "s3"
462
-
463
- @r.ltrim "foo", 0, 1
464
-
465
- assert_equal 2, @r.llen("foo")
466
- assert_equal ["s1", "s2"], @r.lrange("foo", 0, -1)
467
- end
468
-
469
- test "LINDEX" do
470
- @r.rpush "foo", "s1"
471
- @r.rpush "foo", "s2"
472
-
473
- assert_equal "s1", @r.lindex("foo", 0)
474
- assert_equal "s2", @r.lindex("foo", 1)
475
- end
476
-
477
- test "LSET" do
478
- @r.rpush "foo", "s1"
479
- @r.rpush "foo", "s2"
480
-
481
- assert_equal "s2", @r.lindex("foo", 1)
482
- assert @r.lset("foo", 1, "s3")
483
- assert_equal "s3", @r.lindex("foo", 1)
484
-
485
- assert_raises RuntimeError do
486
- @r.lset("foo", 4, "s3")
487
- end
488
- end
489
-
490
- test "LREM" do
491
- @r.rpush "foo", "s1"
492
- @r.rpush "foo", "s2"
493
-
494
- assert_equal 1, @r.lrem("foo", 1, "s1")
495
- assert_equal ["s2"], @r.lrange("foo", 0, -1)
496
- end
497
-
498
- test "LPOP" do
499
- @r.rpush "foo", "s1"
500
- @r.rpush "foo", "s2"
501
-
502
- assert_equal 2, @r.llen("foo")
503
- assert_equal "s1", @r.lpop("foo")
504
- assert_equal 1, @r.llen("foo")
505
- end
506
-
507
- test "RPOP" do
508
- @r.rpush "foo", "s1"
509
- @r.rpush "foo", "s2"
510
-
511
- assert_equal 2, @r.llen("foo")
512
- assert_equal "s2", @r.rpop("foo")
513
- assert_equal 1, @r.llen("foo")
514
- end
515
-
516
- test "RPOPLPUSH" do
517
- assert_raises Redis::Distributed::CannotDistribute do
518
- @r.rpoplpush("foo", "bar")
519
- end
520
- end
521
- end
522
-
523
- context "Blocking commands" do
524
- test "BLPOP" do
525
- @r.lpush("foo", "s1")
526
- @r.lpush("foo", "s2")
527
-
528
- thread = Thread.new do
529
- redis = Redis::Distributed.new(NODES)
530
- sleep 0.3
531
- redis.lpush("foo", "s3")
532
- end
533
-
534
- assert_equal @r.blpop("foo", 0.1), ["foo", "s2"]
535
- assert_equal @r.blpop("foo", 0.1), ["foo", "s1"]
536
- assert_equal @r.blpop("foo", 0.4), ["foo", "s3"]
537
-
538
- thread.join
539
- end
540
-
541
- test "BRPOP" do
542
- @r.rpush("foo", "s1")
543
- @r.rpush("foo", "s2")
544
-
545
- t = Thread.new do
546
- redis = Redis::Distributed.new(NODES)
547
- sleep 0.3
548
- redis.rpush("foo", "s3")
549
- end
550
-
551
- assert_equal @r.brpop("foo", 0.1), ["foo", "s2"]
552
- assert_equal @r.brpop("foo", 0.1), ["foo", "s1"]
553
- assert_equal @r.brpop("foo", 0.4), ["foo", "s3"]
554
-
555
- t.join
556
- end
557
-
558
- test "BRPOP should unset a configured socket timeout" do
559
- @r = Redis::Distributed.new(NODES, :timeout => 1)
560
- assert_nothing_raised do
561
- @r.brpop("foo", 2)
562
- end # Errno::EAGAIN raised if socket times out before redis command times out
563
- end
564
-
565
- test "BRPOP should restore the timeout after the command is run"
566
-
567
- test "BRPOP should restore the timeout even if the command fails"
568
- end
569
-
570
- context "Commands operating on sets" do
571
- test "SADD" do
572
- @r.sadd "foo", "s1"
573
- @r.sadd "foo", "s2"
574
-
575
- assert_equal ["s1", "s2"], @r.smembers("foo").sort
576
- end
577
-
578
- test "SREM" do
579
- @r.sadd "foo", "s1"
580
- @r.sadd "foo", "s2"
581
-
582
- @r.srem("foo", "s1")
583
-
584
- assert_equal ["s2"], @r.smembers("foo")
585
- end
586
-
587
- test "SPOP" do
588
- @r.sadd "foo", "s1"
589
- @r.sadd "foo", "s2"
590
-
591
- assert ["s1", "s2"].include?(@r.spop("foo"))
592
- assert ["s1", "s2"].include?(@r.spop("foo"))
593
- assert_nil @r.spop("foo")
594
- end
595
-
596
- test "SMOVE" do
597
- assert_raises Redis::Distributed::CannotDistribute do
598
- @r.sadd "foo", "s1"
599
- @r.sadd "bar", "s2"
600
-
601
- @r.smove("foo", "bar", "s1")
602
- end
603
- end
604
-
605
- test "SCARD" do
606
- assert_equal 0, @r.scard("foo")
607
-
608
- @r.sadd "foo", "s1"
609
-
610
- assert_equal 1, @r.scard("foo")
611
-
612
- @r.sadd "foo", "s2"
613
-
614
- assert_equal 2, @r.scard("foo")
615
- end
616
-
617
- test "SISMEMBER" do
618
- assert_equal false, @r.sismember("foo", "s1")
619
-
620
- @r.sadd "foo", "s1"
621
-
622
- assert_equal true, @r.sismember("foo", "s1")
623
- assert_equal false, @r.sismember("foo", "s2")
624
- end
625
-
626
- test "SINTER" do
627
- assert_raises Redis::Distributed::CannotDistribute do
628
- @r.sadd "foo", "s1"
629
- @r.sadd "foo", "s2"
630
- @r.sadd "bar", "s2"
631
-
632
- @r.sinter("foo", "bar")
633
- end
634
- end
635
-
636
- test "SINTERSTORE" do
637
- assert_raises Redis::Distributed::CannotDistribute do
638
- @r.sadd "foo", "s1"
639
- @r.sadd "foo", "s2"
640
- @r.sadd "bar", "s2"
641
-
642
- @r.sinterstore("baz", "foo", "bar")
643
- end
644
- end
645
-
646
- test "SUNION" do
647
- assert_raises Redis::Distributed::CannotDistribute do
648
- @r.sadd "foo", "s1"
649
- @r.sadd "foo", "s2"
650
- @r.sadd "bar", "s2"
651
- @r.sadd "bar", "s3"
652
-
653
- @r.sunion("foo", "bar")
654
- end
655
- end
656
-
657
- test "SUNIONSTORE" do
658
- assert_raises Redis::Distributed::CannotDistribute do
659
- @r.sadd "foo", "s1"
660
- @r.sadd "foo", "s2"
661
- @r.sadd "bar", "s2"
662
- @r.sadd "bar", "s3"
663
-
664
- @r.sunionstore("baz", "foo", "bar")
665
- end
666
- end
667
-
668
- test "SDIFF" do
669
- assert_raises Redis::Distributed::CannotDistribute do
670
- @r.sadd "foo", "s1"
671
- @r.sadd "foo", "s2"
672
- @r.sadd "bar", "s2"
673
- @r.sadd "bar", "s3"
674
-
675
- @r.sdiff("foo", "bar")
676
- end
677
- end
678
-
679
- test "SDIFFSTORE" do
680
- assert_raises Redis::Distributed::CannotDistribute do
681
- @r.sadd "foo", "s1"
682
- @r.sadd "foo", "s2"
683
- @r.sadd "bar", "s2"
684
- @r.sadd "bar", "s3"
685
-
686
- @r.sdiffstore("baz", "foo", "bar")
687
- end
688
- end
689
-
690
- test "SMEMBERS" do
691
- assert_equal [], @r.smembers("foo")
692
-
693
- @r.sadd "foo", "s1"
694
- @r.sadd "foo", "s2"
695
-
696
- assert_equal ["s1", "s2"], @r.smembers("foo").sort
697
- end
698
-
699
- test "SRANDMEMBER" do
700
- @r.sadd "foo", "s1"
701
- @r.sadd "foo", "s2"
702
-
703
- 4.times do
704
- assert ["s1", "s2"].include?(@r.srandmember("foo"))
705
- end
706
-
707
- assert_equal 2, @r.scard("foo")
708
- end
709
- end
710
-
711
- context "Commands operating on sorted sets" do
712
- test "ZADD" do
713
- assert_equal 0, @r.zcard("foo")
714
-
715
- @r.zadd "foo", 1, "s1"
716
-
717
- assert_equal 1, @r.zcard("foo")
718
- end
719
-
720
- test "ZREM" do
721
- @r.zadd "foo", 1, "s1"
722
-
723
- assert_equal 1, @r.zcard("foo")
724
-
725
- @r.zadd "foo", 2, "s2"
726
-
727
- assert_equal 2, @r.zcard("foo")
728
-
729
- @r.zrem "foo", "s1"
730
-
731
- assert_equal 1, @r.zcard("foo")
732
- end
733
-
734
- test "ZINCRBY" do
735
- @r.zincrby "foo", 1, "s1"
736
-
737
- assert_equal "1", @r.zscore("foo", "s1")
738
-
739
- @r.zincrby "foo", 10, "s1"
740
-
741
- assert_equal "11", @r.zscore("foo", "s1")
742
- end
743
-
744
- test "ZRANK"
745
-
746
- test "ZREVRANK"
747
-
748
- test "ZRANGE" do
749
- @r.zadd "foo", 1, "s1"
750
- @r.zadd "foo", 2, "s2"
751
- @r.zadd "foo", 3, "s3"
752
-
753
- assert_equal ["s1", "s2"], @r.zrange("foo", 0, 1)
754
- assert_equal ["s1", "1", "s2", "2"], @r.zrange("foo", 0, 1, true)
755
- end
756
-
757
- test "ZREVRANGE" do
758
- @r.zadd "foo", 1, "s1"
759
- @r.zadd "foo", 2, "s2"
760
- @r.zadd "foo", 3, "s3"
761
-
762
- assert_equal ["s3", "s2"], @r.zrevrange("foo", 0, 1)
763
- assert_equal ["s3", "3", "s2", "2"], @r.zrevrange("foo", 0, 1, true)
764
- end
765
-
766
- test "ZRANGEBYSCORE" do
767
- @r.zadd "foo", 1, "s1"
768
- @r.zadd "foo", 2, "s2"
769
- @r.zadd "foo", 3, "s3"
770
-
771
- assert_equal ["s2", "s3"], @r.zrangebyscore("foo", 2, 3)
772
- end
773
-
774
- test "ZRANGEBYSCORE with LIMIT"
775
- test "ZRANGEBYSCORE with WITHSCORES"
776
-
777
- test "ZCARD" do
778
- assert_equal 0, @r.zcard("foo")
779
-
780
- @r.zadd "foo", 1, "s1"
781
-
782
- assert_equal 1, @r.zcard("foo")
783
- end
784
-
785
- test "ZSCORE" do
786
- @r.zadd "foo", 1, "s1"
787
-
788
- assert_equal "1", @r.zscore("foo", "s1")
789
-
790
- assert_nil @r.zscore("foo", "s2")
791
- assert_nil @r.zscore("bar", "s1")
792
- end
793
-
794
- test "ZREMRANGEBYRANK"
795
-
796
- test "ZREMRANGEBYSCORE"
797
-
798
- test "ZUNION"
799
-
800
- test "ZINTER"
801
- end
802
-
803
- context "Commands operating on hashes" do
804
- test "HSET and HGET" do
805
- @r.hset("foo", "f1", "s1")
806
-
807
- assert_equal "s1", @r.hget("foo", "f1")
808
- end
809
-
810
- test "HDEL" do
811
- @r.hset("foo", "f1", "s1")
812
-
813
- assert_equal "s1", @r.hget("foo", "f1")
814
-
815
- @r.hdel("foo", "f1")
816
-
817
- assert_equal nil, @r.hget("foo", "f1")
818
- end
819
-
820
- test "HEXISTS" do
821
- assert_equal false, @r.hexists("foo", "f1")
822
-
823
- @r.hset("foo", "f1", "s1")
824
-
825
- assert @r.hexists("foo", "f1")
826
- end
827
-
828
- test "HLEN" do
829
- assert_equal 0, @r.hlen("foo")
830
-
831
- @r.hset("foo", "f1", "s1")
832
-
833
- assert_equal 1, @r.hlen("foo")
834
-
835
- @r.hset("foo", "f2", "s2")
836
-
837
- assert_equal 2, @r.hlen("foo")
838
- end
839
-
840
- test "HKEYS" do
841
- assert_equal [], @r.hkeys("foo")
842
-
843
- @r.hset("foo", "f1", "s1")
844
- @r.hset("foo", "f2", "s2")
845
-
846
- assert_equal ["f1", "f2"], @r.hkeys("foo")
847
- end
848
-
849
- test "HVALS" do
850
- assert_equal [], @r.hvals("foo")
851
-
852
- @r.hset("foo", "f1", "s1")
853
- @r.hset("foo", "f2", "s2")
854
-
855
- assert_equal ["s1", "s2"], @r.hvals("foo")
856
- end
857
-
858
- test "HGETALL" do
859
- assert_equal({}, @r.hgetall("foo"))
860
-
861
- @r.hset("foo", "f1", "s1")
862
- @r.hset("foo", "f2", "s2")
863
-
864
- assert_equal({"f1" => "s1", "f2" => "s2"}, @r.hgetall("foo"))
865
- end
866
-
867
- test "HMSET" do
868
- @r.hmset("hash", "foo1", "bar1", "foo2", "bar2")
869
-
870
- assert_equal "bar1", @r.hget("hash", "foo1")
871
- assert_equal "bar2", @r.hget("hash", "foo2")
872
- end
873
-
874
- test "HMSET with invalid arguments" do
875
- assert_raises RuntimeError do
876
- @r.hmset("hash", "foo1", "bar1", "foo2", "bar2", "foo3")
877
- end
878
- end
879
- end
880
-
881
- context "Sorting" do
882
- test "SORT" do
883
- assert_raises Redis::Distributed::CannotDistribute do
884
- @r.set("foo:1", "s1")
885
- @r.set("foo:2", "s2")
886
-
887
- @r.rpush("bar", "1")
888
- @r.rpush("bar", "2")
889
-
890
- @r.sort("bar", :get => "foo:*", :limit => [0, 1])
891
- end
892
- end
893
- end
894
-
895
- context "Transactions" do
896
- test "MULTI/DISCARD" do
897
- @foo = nil
898
-
899
- assert_raises Redis::Distributed::CannotDistribute do
900
- @r.multi { @foo = 1 }
901
- end
902
-
903
- assert_nil @foo
904
-
905
- assert_raises Redis::Distributed::CannotDistribute do
906
- @r.discard
907
- end
908
- end
909
- end
910
-
911
- context "Publish/Subscribe" do
912
-
913
- test "SUBSCRIBE and UNSUBSCRIBE"
914
- # do
915
- # thread = Thread.new do
916
- # @r.subscribe("foo") do |on|
917
- # on.subscribe do |channel, total|
918
- # @subscribed = true
919
- # @t1 = total
920
- # end
921
-
922
- # on.message do |channel, message|
923
- # if message == "s1"
924
- # @r.unsubscribe
925
- # @message = message
926
- # end
927
- # end
928
-
929
- # on.unsubscribe do |channel, total|
930
- # @unsubscribed = true
931
- # @t2 = total
932
- # end
933
- # end
934
- # end
935
-
936
- # Redis::Distributed.new(NODES).publish("foo", "s1")
937
-
938
- # thread.join
939
-
940
- # assert @subscribed
941
- # assert_equal 1, @t1
942
- # assert @unsubscribed
943
- # assert_equal 0, @t2
944
- # assert_equal "s1", @message
945
- # end
946
-
947
- test "SUBSCRIBE within SUBSCRIBE"
948
- # do
949
- # @channels = []
950
-
951
- # thread = Thread.new do
952
- # @r.subscribe("foo") do |on|
953
- # on.subscribe do |channel, total|
954
- # @channels << channel
955
-
956
- # @r.subscribe("bar") if channel == "foo"
957
- # @r.unsubscribe if channel == "bar"
958
- # end
959
- # end
960
- # end
961
-
962
- # Redis::Distributed.new(NODES).publish("foo", "s1")
963
-
964
- # thread.join
965
-
966
- # assert_equal ["foo", "bar"], @channels
967
- # end
968
-
969
- test "other commands within a SUBSCRIBE"
970
- # do
971
- # assert_raises RuntimeError do
972
- # @r.subscribe("foo") do |on|
973
- # on.subscribe do |channel, total|
974
- # @r.set("bar", "s2")
975
- # end
976
- # end
977
- # end
978
- # end
979
-
980
- test "SUBSCRIBE without a block"
981
- # do
982
- # assert_raises LocalJumpError do
983
- # @r.subscribe("foo")
984
- # end
985
- # end
986
-
987
- test "SUBSCRIBE timeout"
988
-
989
- end
990
-
991
- context "Persistence control commands" do
992
- test "SAVE and BGSAVE" do
993
- assert_nothing_raised do
994
- @r.save
995
- end
996
-
997
- assert_nothing_raised do
998
- @r.bgsave
999
- end
1000
- end
1001
-
1002
- test "LASTSAVE" do
1003
- assert @r.lastsave.all? { |t| Time.at(t) <= Time.now }
1004
- end
1005
- end
1006
-
1007
- context "Remote server control commands" do
1008
- test "INFO" do
1009
- %w(last_save_time redis_version total_connections_received connected_clients total_commands_processed connected_slaves uptime_in_seconds used_memory uptime_in_days changes_since_last_save).each do |x|
1010
- @r.info.each do |info|
1011
- assert info.keys.include?(x)
1012
- end
1013
- end
1014
- end
1015
-
1016
- test "MONITOR" do
1017
- assert_raises NotImplementedError do
1018
- @r.monitor
1019
- end
1020
- end
1021
-
1022
- test "ECHO" do
1023
- assert_equal ["foo bar baz\n"], @r.echo("foo bar baz\n")
1024
- end
1025
- end
1026
-
1027
- context "Distributed" do
1028
- test "handle multiple servers" do
1029
- @r = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
1030
-
1031
- 100.times do |idx|
1032
- @r.set(idx.to_s, "foo#{idx}")
1033
- end
1034
-
1035
- 100.times do |idx|
1036
- assert_equal "foo#{idx}", @r.get(idx.to_s)
1037
- end
1038
-
1039
- assert_equal "0", @r.keys("*").sort.first
1040
- assert_equal "string", @r.type("1")
1041
- end
1042
-
1043
- test "add nodes" do
1044
- logger = Logger.new("/dev/null")
1045
-
1046
- @r = Redis::Distributed.new NODES, :logger => logger, :timeout => 10
1047
-
1048
- assert_equal "127.0.0.1", @r.nodes[0].client.host
1049
- assert_equal 6379, @r.nodes[0].client.port
1050
- assert_equal 15, @r.nodes[0].client.db
1051
- assert_equal 10, @r.nodes[0].client.timeout
1052
- assert_equal logger, @r.nodes[0].client.logger
1053
-
1054
- @r.add_node("redis://localhost:6380/14")
1055
-
1056
- assert_equal "localhost", @r.nodes[1].client.host
1057
- assert_equal 6380, @r.nodes[1].client.port
1058
- assert_equal 14, @r.nodes[1].client.db
1059
- assert_equal 10, @r.nodes[1].client.timeout
1060
- assert_equal logger, @r.nodes[1].client.logger
1061
- end
1062
- end
1063
-
1064
- context "Pipelining commands" do
1065
- test "cannot be distributed" do
1066
- assert_raises Redis::Distributed::CannotDistribute do
1067
- @r.pipelined do
1068
- @r.lpush "foo", "s1"
1069
- @r.lpush "foo", "s2"
1070
- end
1071
- end
1072
- end
1073
- end
1074
-
1075
- context "Unknown commands" do
1076
- should "not work by default" do
1077
- assert_raises NoMethodError do
1078
- @r.not_yet_implemented_command
1079
- end
1080
- end
1081
- end
1082
-
1083
- context "Key tags" do
1084
- should "hash consistently" do
1085
- r1 = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
1086
- r2 = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
1087
- r3 = Redis::Distributed.new ["redis://localhost:6379/15", *NODES]
1088
-
1089
- assert r1.node_for("foo").id == r2.node_for("foo").id
1090
- assert r1.node_for("foo").id == r3.node_for("foo").id
1091
- end
1092
-
1093
- should "allow clustering of keys" do
1094
- @r = Redis::Distributed.new(NODES)
1095
- @r.add_node("redis://localhost:6379/14")
1096
- @r.flushdb
1097
-
1098
- 100.times do |i|
1099
- @r.set "{foo}users:#{i}", i
1100
- end
1101
-
1102
- assert_equal [0, 100], @r.nodes.map { |node| node.keys.size }
1103
- end
1104
-
1105
- should "distribute keys if no clustering is used" do
1106
- @r.add_node("redis://localhost:6379/14")
1107
- @r.flushdb
1108
-
1109
- @r.set "users:1", 1
1110
- @r.set "users:4", 4
1111
-
1112
- assert_equal [1, 1], @r.nodes.map { |node| node.keys.size }
1113
- end
1114
-
1115
- should "allow passing a custom tag extractor" do
1116
- @r = Redis::Distributed.new(NODES, :tag => /^(.+?):/)
1117
- @r.add_node("redis://localhost:6379/14")
1118
- @r.flushdb
1119
-
1120
- 100.times do |i|
1121
- @r.set "foo:users:#{i}", i
1122
- end
1123
-
1124
- assert_equal [0, 100], @r.nodes.map { |node| node.keys.size }
1125
- end
1126
- end
1127
-
1128
- teardown do
1129
- @r.nodes.each { |node| node.client.disconnect }
1130
- end
1131
- end