superfeedr-em-redis 0.2.6 → 0.2.7

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -18,7 +18,7 @@ Bones {
18
18
  authors ['Jonathan Broad', 'Eugene Pimenov', 'Stephan Maka']
19
19
  email 'stephan@spaceboyz.net'
20
20
  url 'http://github.com/astro/em-redis'
21
- summary 'An eventmachine-based implementation of the Redis protocol (forked)'
21
+ summary 'An eventmachine-based implementation of the Redis protocol'
22
22
  description summary
23
23
  version EMRedis::VERSION
24
24
 
@@ -2,7 +2,7 @@
2
2
  module EMRedis
3
3
 
4
4
  # :stopdoc:
5
- VERSION = '0.2.6'
5
+ VERSION = '0.2.7'
6
6
  LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
7
7
  PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
8
8
  # :startdoc:
@@ -34,12 +34,16 @@ module EventMachine
34
34
  "zadd" => true,
35
35
  "zincrby" => true,
36
36
  "zrem" => true,
37
- "zscore" => true
37
+ "zscore" => true,
38
+ "hget" => true,
39
+ "hdel" => true,
40
+ "hexists" => true
38
41
  }
39
42
 
40
43
  MULTI_BULK_COMMANDS = {
41
44
  "mset" => true,
42
45
  "msetnx" => true,
46
+ "hset" => true,
43
47
  # these aliases aren't in redis gem
44
48
  "multi_get" => true
45
49
  }
@@ -60,7 +64,16 @@ module EventMachine
60
64
  "renamenx" => BOOLEAN_PROCESSOR,
61
65
  "expire" => BOOLEAN_PROCESSOR,
62
66
  "select" => BOOLEAN_PROCESSOR, # not in redis gem
63
- "keys" => lambda{|r| r.split(" ")},
67
+ "hset" => BOOLEAN_PROCESSOR,
68
+ "hdel" => BOOLEAN_PROCESSOR,
69
+ "hexists" => BOOLEAN_PROCESSOR,
70
+ "keys" => lambda {|r|
71
+ if r.is_a?(Array)
72
+ r
73
+ else
74
+ r.split(" ")
75
+ end
76
+ },
64
77
  "info" => lambda{|r|
65
78
  info = {}
66
79
  r.each_line {|kv|
@@ -68,6 +81,9 @@ module EventMachine
68
81
  info[k.to_sym] = v
69
82
  }
70
83
  info
84
+ },
85
+ "hgetall" => lambda{|r|
86
+ Hash[*r]
71
87
  }
72
88
  }
73
89
 
@@ -218,64 +234,80 @@ module EventMachine
218
234
  call_command(['quit'], &blk)
219
235
  end
220
236
 
221
- def errback(&blk)
222
- @error_callback = blk
237
+ def exec(&blk)
238
+ call_command(['exec'], &blk)
223
239
  end
224
- alias_method :on_error, :errback
225
240
 
226
- def method_missing(*argv, &blk)
227
- call_command(argv, &blk)
241
+ # I'm not sure autocommit is a good idea.
242
+ # For example:
243
+ # r.multi { r.set('a', 'b') { raise "kaboom" } }
244
+ # will commit "a" and will stop EM
245
+ def multi
246
+ call_command(['multi'])
247
+ if block_given?
248
+ begin
249
+ yield self
250
+ exec
251
+ rescue Exception => e
252
+ discard
253
+ raise e
254
+ end
255
+ end
228
256
  end
229
257
 
230
- def call_command(argv, &blk)
231
- callback { raw_call_command(argv, &blk) }
258
+ def mset(*args, &blk)
259
+ hsh = args.pop if Hash === args.last
260
+ if hsh
261
+ call_command(hsh.to_a.flatten.unshift(:mset), &blk)
262
+ else
263
+ call_command(args.unshift(:mset), &blk)
264
+ end
232
265
  end
233
266
 
234
- def raw_call_command(argv, &blk)
235
- argv[0] = argv[0].to_s unless argv[0].kind_of? String
236
- send_command(argv)
237
- @redis_callbacks << [REPLY_PROCESSOR[argv[0]], blk]
267
+ def msetnx(*args, &blk)
268
+ hsh = args.pop if Hash === args.last
269
+ if hsh
270
+ call_command(hsh.to_a.flatten.unshift(:msetnx), &blk)
271
+ else
272
+ call_command(args.unshift(:msetnx), &blk)
273
+ end
238
274
  end
239
275
 
240
- def call_commands(argvs, &blk)
241
- callback { raw_call_commands(argvs, &blk) }
276
+ def errback(&blk)
277
+ @error_callback = blk
242
278
  end
279
+ alias_method :on_error, :errback
243
280
 
244
- def raw_call_commands(argvs, &blk)
245
- if argvs.empty? # Shortcut
246
- blk.call []
247
- return
248
- end
281
+ def method_missing(*argv, &blk)
282
+ call_command(argv, &blk)
283
+ end
249
284
 
250
- argvs.each do |argv|
251
- argv[0] = argv[0].to_s unless argv[0].kind_of? String
252
- send_command argv
285
+ def maybe_lock(&blk)
286
+ if !EM.reactor_thread?
287
+ EM.schedule { maybe_lock(&blk) }
288
+ elsif @connected
289
+ yield
290
+ else
291
+ callback { yield }
253
292
  end
254
- # FIXME: argvs may contain heterogenous commands, storing all
255
- # REPLY_PROCESSORs may turn out expensive and has been omitted
256
- # for now.
257
- @redis_callbacks << [nil, argvs.length, blk]
258
293
  end
259
294
 
260
- def send_command(argv)
295
+ def call_command(argv, &blk)
261
296
  argv = argv.dup
262
297
 
263
- if MULTI_BULK_COMMANDS[argv.flatten[0].to_s]
264
- # TODO improve this code
265
- argvp = argv.flatten
266
- values = argvp.pop.to_a.flatten
267
- argvp = values.unshift(argvp[0])
268
- command = ["*#{argvp.size}"]
269
- argvp.each do |v|
270
- v = v.to_s
271
- command << "$#{get_size(v)}"
272
- command << v
298
+ argv[0] = argv[0].to_s.downcase
299
+ if MULTI_BULK_COMMANDS[argv[0]]
300
+ command = ""
301
+ command << "*#{argv.size}\r\n"
302
+ argv.each do |a|
303
+ a = a.to_s
304
+ command << "$#{get_size(a)}\r\n"
305
+ command << a
306
+ command << "\r\n"
273
307
  end
274
- command = command.map {|cmd| "#{cmd}\r\n"}.join
275
308
  else
276
309
  command = ""
277
310
  bulk = nil
278
- argv[0] = argv[0].to_s.downcase
279
311
  argv[0] = ALIASES[argv[0]] if ALIASES[argv[0]]
280
312
  raise "#{argv[0]} command is disabled" if DISABLED_COMMANDS[argv[0]]
281
313
  if BULK_COMMANDS[argv[0]] and argv.length > 1
@@ -287,7 +319,27 @@ module EventMachine
287
319
  end
288
320
 
289
321
  @logger.debug { "*** sending: #{command}" } if @logger
290
- send_data command
322
+ maybe_lock do
323
+ @redis_callbacks << [REPLY_PROCESSOR[argv[0]], blk]
324
+ send_data command
325
+ end
326
+ end
327
+
328
+ def call_commands(argvs, &blk)
329
+ pending = 0
330
+ results = []
331
+ check = lambda {
332
+ blk.call(results) if pending < 1
333
+ }
334
+ argvs.each do |argv|
335
+ call_command(argv) { |result|
336
+ results << result
337
+ pending -= 1
338
+ check.call
339
+ }
340
+ pending += 1
341
+ end
342
+ check.call
291
343
  end
292
344
 
293
345
  ##
@@ -318,7 +370,7 @@ module EventMachine
318
370
  else raise ArgumentError, 'first argument must be Hash or String'
319
371
  end
320
372
  when 2
321
- options = {:host => args[1], :port => args[2]}
373
+ options = {:host => args[0], :port => args[1]}
322
374
  else
323
375
  raise ArgumentError, "wrong number of arguments (#{args.length} for 1)"
324
376
  end
@@ -338,7 +390,6 @@ module EventMachine
338
390
  err.code = code
339
391
  raise err, "Redis server returned error code: #{code}"
340
392
  end
341
- @values = []
342
393
 
343
394
  # These commands should be first
344
395
  auth_and_select_db
@@ -410,10 +461,11 @@ module EventMachine
410
461
  #e.g. *2\r\n$1\r\na\r\n$1\r\nb\r\n
411
462
  when ASTERISK
412
463
  multibulk_count = Integer(reply_args)
413
- if multibulk_count == -1
464
+ if multibulk_count == -1 || multibulk_count == 0
414
465
  dispatch_response([])
415
466
  else
416
- start_multibulk(multibulk_count)
467
+ @multibulk_n = multibulk_count
468
+ @multibulk_values = []
417
469
  end
418
470
  # Whu?
419
471
  else
@@ -53,14 +53,14 @@ EM.describe EM::Protocols::Redis, "connected to an empty db" do
53
53
 
54
54
  should "be able to 'lpush' to a nonexistent list" do
55
55
  @c.lpush("foo", "bar") do |r|
56
- r.should == "OK"
56
+ r.should == 1
57
57
  done
58
58
  end
59
59
  end
60
60
 
61
61
  should "be able to 'rpush' to a nonexistent list" do
62
62
  @c.rpush("foo", "bar") do |r|
63
- r.should == "OK"
63
+ r.should == 1
64
64
  done
65
65
  end
66
66
  end
@@ -222,7 +222,7 @@ EM.describe EM::Protocols::Redis, "connected to a db containing a list" do
222
222
 
223
223
  should "be able to 'rpush' onto the tail of the list" do
224
224
  @c.rpush "foo", "d" do |r|
225
- r.should == "OK"
225
+ r.should == 4
226
226
  @c.rpop "foo" do |r|
227
227
  r.should == "d"
228
228
  done
@@ -232,7 +232,7 @@ EM.describe EM::Protocols::Redis, "connected to a db containing a list" do
232
232
 
233
233
  should "be able to 'lpush' onto the head of the list" do
234
234
  @c.lpush "foo", "d" do |r|
235
- r.should == "OK"
235
+ r.should == 4
236
236
  @c.lpop "foo" do |r|
237
237
  r.should == "d"
238
238
  done
@@ -10,6 +10,7 @@ EM.describe EM::Protocols::Redis do
10
10
  @r['foo'] = 'bar'
11
11
  end
12
12
 
13
+ after { @r.close_connection }
13
14
 
14
15
  should "be able to provide a logger" do
15
16
  log = StringIO.new
@@ -644,6 +645,90 @@ EM.describe EM::Protocols::Redis do
644
645
  # done
645
646
  # end
646
647
 
648
+ it "should run MULTI without a block" do
649
+ @r.multi
650
+ @r.get("key1") { |r| r.should == "QUEUED" }
651
+ @r.discard { done }
652
+ end
653
+
654
+ it "should run MULTI/EXEC with a block" do
655
+ @r.multi do
656
+ @r.set "key1", "value1"
657
+ end
658
+
659
+ @r.get("key1") { |r| r.should == "value1" }
660
+
661
+ begin
662
+ @r.multi do
663
+ @r.set "key2", "value2"
664
+ raise "Some error"
665
+ @r.set "key3", "value3"
666
+ end
667
+ rescue
668
+ end
669
+
670
+ @r.get("key2") { |r| r.should == nil }
671
+ @r.get("key3") { |r| r.should == nil; done}
672
+ end
673
+
674
+ it "should yield the Redis object when using #multi with a block" do
675
+ @r.multi do |multi|
676
+ multi.set "key1", "value1"
677
+ end
678
+
679
+ @r.get("key1") { |r| r.should == "value1"; done }
680
+ end
681
+
682
+ it "can set and get hash values" do
683
+ @r.hset("rush", "signals", "1982") { |r| r.should == true }
684
+ @r.hexists("rush", "signals") { |r| r.should == true }
685
+ @r.hget("rush", "signals") { |r| r.should == "1982"; done }
686
+ end
687
+
688
+ it "can delete hash values" do
689
+ @r.hset("rush", "YYZ", "1981")
690
+ @r.hdel("rush", "YYZ") { |r| r.should == true }
691
+ @r.hexists("rush", "YYZ") { |r| r.should == false; done }
692
+ end
693
+ end
694
+
695
+ # Yup, bacon can't handle nested describe blocks properly
696
+ EM.describe EM::Protocols::Redis, "with some hash values" do
697
+ default_timeout 1
698
+
699
+ before do
700
+ @r = EM::Protocols::Redis.connect :db => 14
701
+ @r.flushdb
702
+ @r['foo'] = 'bar'
703
+ @r.hset("rush", "permanent waves", "1980")
704
+ @r.hset("rush", "moving pictures", "1981")
705
+ @r.hset("rush", "signals", "1982")
706
+ end
707
+
708
+ after { @r.close_connection }
709
+
710
+ it "can get the length of the hash" do
711
+ @r.hlen("rush") { |r| r.should == 3 }
712
+ @r.hlen("yyz") { |r| r.should == 0; done }
713
+ end
714
+
715
+ it "can get the keys and values of the hash" do
716
+ @r.hkeys("rush") { |r| r.should == ["permanent waves", "moving pictures", "signals"] }
717
+ @r.hvals("rush") { |r| r.should == %w[1980 1981 1982] }
718
+ @r.hvals("yyz") { |r| r.should == []; done }
719
+ end
720
+
721
+ it "returns a hash for HGETALL" do
722
+ @r.hgetall("rush") do |r|
723
+ r.should == {
724
+ "permanent waves" => "1980",
725
+ "moving pictures" => "1981",
726
+ "signals" => "1982"
727
+ }
728
+ end
729
+ @r.hgetall("yyz") { |r| r.should == {}; done }
730
+ end
731
+
647
732
  it "should work with 10 commands" do
648
733
  @r.call_commands((1..10).map { |i|
649
734
  ['get', "foo"]
@@ -0,0 +1,731 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/test_helper.rb")
2
+ require 'logger'
3
+
4
+ EM.describe EM::Protocols::Redis do
5
+ default_timeout 1
6
+
7
+ before do
8
+ @r = EM::Protocols::Redis.connect :db => 14
9
+ @r.flushdb
10
+ @r['foo'] = 'bar'
11
+ end
12
+
13
+ after { @r.close_connection }
14
+
15
+ should "be able to provide a logger" do
16
+ log = StringIO.new
17
+ r = EM::Protocols::Redis.connect :db => 14, :logger => Logger.new(log)
18
+ r.ping do
19
+ log.string.should.include "ping"
20
+ done
21
+ end
22
+ end
23
+
24
+ it "should be able to PING" do
25
+ @r.ping { |r| r.should == 'PONG'; done }
26
+ end
27
+
28
+ it "should be able to GET a key" do
29
+ @r.get('foo') { |r| r.should == 'bar'; done }
30
+ end
31
+
32
+ it "should be able to SET a key" do
33
+ @r['foo'] = 'nik'
34
+ @r.get('foo') { |r| r.should == 'nik'; done }
35
+ end
36
+
37
+ it "should properly handle trailing newline characters" do
38
+ @r['foo'] = "bar\n"
39
+ @r.get('foo') { |r| r.should == "bar\n"; done }
40
+ end
41
+
42
+ it "should store and retrieve all possible characters at the beginning and the end of a string" do
43
+ (0..255).each do |char_idx|
44
+ string = "#{char_idx.chr}---#{char_idx.chr}"
45
+ @r['foo'] = string
46
+ @r.get('foo') { |r| r.should == string }
47
+ end
48
+ @r.ping { done }
49
+ end
50
+
51
+ it "should be able to SET a key with an expiry" do
52
+ timeout(3)
53
+
54
+ @r.set('foo', 'bar', 1)
55
+ @r.get('foo') { |r| r.should == 'bar' }
56
+ EM.add_timer(2) do
57
+ @r.get('foo') { |r| r.should == nil }
58
+ @r.ping { done }
59
+ end
60
+ end
61
+
62
+ it "should be able to return a TTL for a key" do
63
+ @r.set('foo', 'bar', 1)
64
+ @r.ttl('foo') { |r| r.should == 1; done }
65
+ end
66
+
67
+ it "should be able to SETNX" do
68
+ @r['foo'] = 'nik'
69
+ @r.get('foo') { |r| r.should == 'nik' }
70
+ @r.setnx 'foo', 'bar'
71
+ @r.get('foo') { |r| r.should == 'nik' }
72
+
73
+ @r.ping { done }
74
+ end
75
+ #
76
+ it "should be able to GETSET" do
77
+ @r.getset('foo', 'baz') { |r| r.should == 'bar' }
78
+ @r.get('foo') { |r| r.should == 'baz'; done }
79
+ end
80
+ #
81
+ it "should be able to INCR a key" do
82
+ @r.del('counter')
83
+ @r.incr('counter') { |r| r.should == 1 }
84
+ @r.incr('counter') { |r| r.should == 2 }
85
+ @r.incr('counter') { |r| r.should == 3 }
86
+
87
+ @r.ping { done }
88
+ end
89
+ #
90
+ it "should be able to INCRBY a key" do
91
+ @r.del('counter')
92
+ @r.incrby('counter', 1) { |r| r.should == 1 }
93
+ @r.incrby('counter', 2) { |r| r.should == 3 }
94
+ @r.incrby('counter', 3) { |r| r.should == 6 }
95
+
96
+ @r.ping { done }
97
+ end
98
+ #
99
+ it "should be able to DECR a key" do
100
+ @r.del('counter')
101
+ @r.incr('counter') { |r| r.should == 1 }
102
+ @r.incr('counter') { |r| r.should == 2 }
103
+ @r.incr('counter') { |r| r.should == 3 }
104
+ @r.decr('counter') { |r| r.should == 2 }
105
+ @r.decr('counter', 2) { |r| r.should == 0; done }
106
+ end
107
+ #
108
+ it "should be able to RANDKEY" do
109
+ @r.randkey { |r| r.should.not == nil; done }
110
+ end
111
+ #
112
+ it "should be able to RENAME a key" do
113
+ @r.del 'foo'
114
+ @r.del 'bar'
115
+ @r['foo'] = 'hi'
116
+ @r.rename 'foo', 'bar'
117
+ @r.get('bar') { |r| r.should == 'hi' ; done }
118
+ end
119
+ #
120
+ it "should be able to RENAMENX a key" do
121
+ @r.del 'foo'
122
+ @r.del 'bar'
123
+ @r['foo'] = 'hi'
124
+ @r['bar'] = 'ohai'
125
+ @r.renamenx 'foo', 'bar'
126
+ @r.get('bar') { |r| r.should == 'ohai' ; done }
127
+ end
128
+ #
129
+ it "should be able to get DBSIZE of the database" do
130
+ dbsize_without_foo, dbsize_with_foo = nil
131
+ @r.delete 'foo'
132
+ @r.dbsize { |r| dbsize_without_foo = r }
133
+ @r['foo'] = 0
134
+ @r.dbsize { |r| dbsize_with_foo = r }
135
+
136
+ @r.ping do
137
+ dbsize_with_foo.should == dbsize_without_foo + 1
138
+ done
139
+ end
140
+ end
141
+ #
142
+ it "should be able to EXPIRE a key" do
143
+ timeout(3)
144
+
145
+ @r['foo'] = 'bar'
146
+ @r.expire 'foo', 1
147
+ @r.get('foo') { |r| r.should == "bar" }
148
+ EM.add_timer(2) do
149
+ @r.get('foo') { |r| r.should == nil }
150
+ @r.ping { done }
151
+ end
152
+ end
153
+ #
154
+ it "should be able to EXISTS" do
155
+ @r['foo'] = 'nik'
156
+ @r.exists('foo') { |r| r.should == true }
157
+ @r.del 'foo'
158
+ @r.exists('foo') { |r| r.should == false ; done }
159
+ end
160
+ #
161
+ it "should be able to KEYS" do
162
+ @r.keys("f*") { |keys| keys.each { |key| @r.del key } }
163
+ @r['f'] = 'nik'
164
+ @r['fo'] = 'nak'
165
+ @r['foo'] = 'qux'
166
+ @r.keys("f*") { |r| r.sort.should == ['f', 'fo', 'foo'].sort }
167
+
168
+ @r.ping { done }
169
+ end
170
+ #
171
+ it "should be able to return a random key (RANDOMKEY)" do
172
+ 3.times do |i|
173
+ @r.randomkey do |r|
174
+ @r.exists(r) do |e|
175
+ e.should == true
176
+ done if i == 2
177
+ end
178
+ end
179
+ end
180
+ end
181
+ #
182
+ it "should be able to check the TYPE of a key" do
183
+ @r['foo'] = 'nik'
184
+ @r.type('foo') { |r| r.should == "string" }
185
+ @r.del 'foo'
186
+ @r.type('foo') { |r| r.should == "none" ; done }
187
+ end
188
+ #
189
+ it "should be able to push to the head of a list (LPUSH)" do
190
+ @r.lpush "list", 'hello'
191
+ @r.lpush "list", 42
192
+ @r.type('list') { |r| r.should == "list" }
193
+ @r.llen('list') { |r| r.should == 2 }
194
+ @r.lpop('list') { |r| r.should == '42'; done }
195
+ end
196
+ #
197
+ it "should be able to push to the tail of a list (RPUSH)" do
198
+ @r.rpush "list", 'hello'
199
+ @r.type('list') { |r| r.should == "list" }
200
+ @r.llen('list') { |r| r.should == 1 ; done }
201
+ end
202
+ #
203
+ it "should be able to pop the tail of a list (RPOP)" do
204
+ @r.rpush "list", 'hello'
205
+ @r.rpush"list", 'goodbye'
206
+ @r.type('list') { |r| r.should == "list" }
207
+ @r.llen('list') { |r| r.should == 2 }
208
+ @r.rpop('list') { |r| r.should == 'goodbye'; done }
209
+ end
210
+ #
211
+ it "should be able to pop the head of a list (LPOP)" do
212
+ @r.rpush "list", 'hello'
213
+ @r.rpush "list", 'goodbye'
214
+ @r.type('list') { |r| r.should == "list" }
215
+ @r.llen('list') { |r| r.should == 2 }
216
+ @r.lpop('list') { |r| r.should == 'hello'; done }
217
+ end
218
+ #
219
+ it "should be able to get the length of a list (LLEN)" do
220
+ @r.rpush "list", 'hello'
221
+ @r.rpush "list", 'goodbye'
222
+ @r.type('list') { |r| r.should == "list" }
223
+ @r.llen('list') { |r| r.should == 2 ; done }
224
+ end
225
+ #
226
+ it "should be able to get a range of values from a list (LRANGE)" do
227
+ @r.rpush "list", 'hello'
228
+ @r.rpush "list", 'goodbye'
229
+ @r.rpush "list", '1'
230
+ @r.rpush "list", '2'
231
+ @r.rpush "list", '3'
232
+ @r.type('list') { |r| r.should == "list" }
233
+ @r.llen('list') { |r| r.should == 5 }
234
+ @r.lrange('list', 2, -1) { |r| r.should == ['1', '2', '3']; done }
235
+ end
236
+ #
237
+ it "should be able to trim a list (LTRIM)" do
238
+ @r.rpush "list", 'hello'
239
+ @r.rpush "list", 'goodbye'
240
+ @r.rpush "list", '1'
241
+ @r.rpush "list", '2'
242
+ @r.rpush "list", '3'
243
+ @r.type('list') { |r| r.should == "list" }
244
+ @r.llen('list') { |r| r.should == 5 }
245
+ @r.ltrim 'list', 0, 1
246
+ @r.llen('list') { |r| r.should == 2 }
247
+ @r.lrange('list', 0, -1) { |r| r.should == ['hello', 'goodbye']; done }
248
+ end
249
+ #
250
+ it "should be able to get a value by indexing into a list (LINDEX)" do
251
+ @r.rpush "list", 'hello'
252
+ @r.rpush "list", 'goodbye'
253
+ @r.type('list') { |r| r.should == "list" }
254
+ @r.llen('list') { |r| r.should == 2 }
255
+ @r.lindex('list', 1) { |r| r.should == 'goodbye'; done }
256
+ end
257
+ #
258
+ it "should be able to set a value by indexing into a list (LSET)" do
259
+ @r.rpush "list", 'hello'
260
+ @r.rpush "list", 'hello'
261
+ @r.type('list') { |r| r.should == "list" }
262
+ @r.llen('list') { |r| r.should == 2 }
263
+ @r.lset('list', 1, 'goodbye') { |r| r.should == 'OK' }
264
+ @r.lindex('list', 1) { |r| r.should == 'goodbye'; done }
265
+ end
266
+ #
267
+ it "should be able to remove values from a list (LREM)" do
268
+ @r.rpush "list", 'hello'
269
+ @r.rpush "list", 'goodbye'
270
+ @r.type('list') { |r| r.should == "list" }
271
+ @r.llen('list') { |r| r.should == 2 }
272
+ @r.lrem('list', 1, 'hello') { |r| r.should == 1 }
273
+ @r.lrange('list', 0, -1) { |r| r.should == ['goodbye']; done }
274
+ end
275
+
276
+ it "should be able to pop values from a list and push them onto a temp list(RPOPLPUSH)" do
277
+ @r.rpush "list", 'one'
278
+ @r.rpush "list", 'two'
279
+ @r.rpush "list", 'three'
280
+ @r.type('list') { |r| r.should == "list" }
281
+ @r.llen('list') { |r| r.should == 3 }
282
+ @r.lrange('list', 0, -1) { |r| r.should == ['one', 'two', 'three'] }
283
+ @r.lrange('tmp', 0, -1) { |r| r.should == [] }
284
+ @r.rpoplpush('list', 'tmp') { |r| r.should == 'three' }
285
+ @r.lrange('tmp', 0, -1) { |r| r.should == ['three'] }
286
+ @r.rpoplpush('list', 'tmp') { |r| r.should == 'two' }
287
+ @r.lrange('tmp', 0, -1) { |r| r.should == ['two', 'three'] }
288
+ @r.rpoplpush('list', 'tmp') { |r| r.should == 'one' }
289
+ @r.lrange('tmp', 0, -1) { |r| r.should == ['one', 'two', 'three']; done }
290
+ end
291
+ #
292
+ it "should be able add members to a set (SADD)" do
293
+ @r.sadd "set", 'key1'
294
+ @r.sadd "set", 'key2'
295
+ @r.type('set') { |r| r.should == "set" }
296
+ @r.scard('set') { |r| r.should == 2 }
297
+ @r.smembers('set') { |r| r.sort.should == ['key1', 'key2'].sort; done }
298
+ end
299
+ #
300
+ it "should be able delete members to a set (SREM)" do
301
+ @r.sadd "set", 'key1'
302
+ @r.sadd "set", 'key2'
303
+ @r.type('set') { |r| r.should == "set" }
304
+ @r.scard('set') { |r| r.should == 2 }
305
+ @r.smembers('set') { |r| r.sort.should == ['key1', 'key2'].sort }
306
+ @r.srem('set', 'key1')
307
+ @r.scard('set') { |r| r.should == 1 }
308
+ @r.smembers('set') { |r| r.should == ['key2']; done }
309
+ end
310
+ #
311
+ it "should be able to return and remove random key from set (SPOP)" do
312
+ @r.sadd "set_pop", "key1"
313
+ @r.sadd "set_pop", "key2"
314
+ @r.spop("set_pop") { |r| r.should.not == nil }
315
+ @r.scard("set_pop") { |r| r.should == 1; done }
316
+ end
317
+ #
318
+ it "should be able to return random key without delete the key from a set (SRANDMEMBER)" do
319
+ @r.sadd "set_srandmember", "key1"
320
+ @r.sadd "set_srandmember", "key2"
321
+ @r.srandmember("set_srandmember") { |r| r.should.not == nil }
322
+ @r.scard("set_srandmember") { |r| r.should == 2; done }
323
+ end
324
+ #
325
+ it "should be able count the members of a set (SCARD)" do
326
+ @r.sadd "set", 'key1'
327
+ @r.sadd "set", 'key2'
328
+ @r.type('set') { |r| r.should == "set" }
329
+ @r.scard('set') { |r| r.should == 2; done }
330
+ end
331
+ #
332
+ it "should be able test for set membership (SISMEMBER)" do
333
+ @r.sadd "set", 'key1'
334
+ @r.sadd "set", 'key2'
335
+ @r.type('set') { |r| r.should == "set" }
336
+ @r.scard('set') { |r| r.should == 2 }
337
+ @r.sismember('set', 'key1') { |r| r.should == true }
338
+ @r.sismember('set', 'key2') { |r| r.should == true }
339
+ @r.sismember('set', 'notthere') { |r| r.should == false; done }
340
+ end
341
+ #
342
+ it "should be able to do set intersection (SINTER)" do
343
+ @r.sadd "set", 'key1'
344
+ @r.sadd "set", 'key2'
345
+ @r.sadd "set2", 'key2'
346
+ @r.sinter('set', 'set2') { |r| r.should == ['key2']; done }
347
+ end
348
+ #
349
+ it "should be able to do set intersection and store the results in a key (SINTERSTORE)" do
350
+ @r.sadd "set", 'key1'
351
+ @r.sadd "set", 'key2'
352
+ @r.sadd "set2", 'key2'
353
+ @r.sinterstore('newone', 'set', 'set2') { |r| r.should == 1 }
354
+ @r.smembers('newone') { |r| r.should == ['key2']; done }
355
+ end
356
+ #
357
+ it "should be able to do set union (SUNION)" do
358
+ @r.sadd "set", 'key1'
359
+ @r.sadd "set", 'key2'
360
+ @r.sadd "set2", 'key2'
361
+ @r.sadd "set2", 'key3'
362
+ @r.sunion('set', 'set2') { |r| r.sort.should == ['key1','key2','key3'].sort; done }
363
+ end
364
+ #
365
+ it "should be able to do set union and store the results in a key (SUNIONSTORE)" do
366
+ @r.sadd "set", 'key1'
367
+ @r.sadd "set", 'key2'
368
+ @r.sadd "set2", 'key2'
369
+ @r.sadd "set2", 'key3'
370
+ @r.sunionstore('newone', 'set', 'set2') { |r| r.should == 3 }
371
+ @r.smembers('newone') { |r| r.sort.should == ['key1','key2','key3'].sort; done }
372
+ end
373
+ #
374
+ it "should be able to do set difference (SDIFF)" do
375
+ @r.sadd "set", 'a'
376
+ @r.sadd "set", 'b'
377
+ @r.sadd "set2", 'b'
378
+ @r.sadd "set2", 'c'
379
+ @r.sdiff('set', 'set2') { |r| r.should == ['a']; done }
380
+ end
381
+ #
382
+ it "should be able to do set difference and store the results in a key (SDIFFSTORE)" do
383
+ @r.sadd "set", 'a'
384
+ @r.sadd "set", 'b'
385
+ @r.sadd "set2", 'b'
386
+ @r.sadd "set2", 'c'
387
+ @r.sdiffstore('newone', 'set', 'set2')
388
+ @r.smembers('newone') { |r| r.should == ['a']; done }
389
+ end
390
+ #
391
+ it "should be able move elements from one set to another (SMOVE)" do
392
+ @r.sadd 'set1', 'a'
393
+ @r.sadd 'set1', 'b'
394
+ @r.sadd 'set2', 'x'
395
+ @r.smove('set1', 'set2', 'a') { |r| r.should == true }
396
+ @r.sismember('set2', 'a') { |r| r.should == true }
397
+ @r.delete('set1') { done }
398
+ end
399
+ #
400
+ it "should be able to do crazy SORT queries" do
401
+ # The 'Dogs' is capitialized on purpose
402
+ @r['dog_1'] = 'louie'
403
+ @r.rpush 'Dogs', 1
404
+ @r['dog_2'] = 'lucy'
405
+ @r.rpush 'Dogs', 2
406
+ @r['dog_3'] = 'max'
407
+ @r.rpush 'Dogs', 3
408
+ @r['dog_4'] = 'taj'
409
+ @r.rpush 'Dogs', 4
410
+ @r.sort('Dogs', :get => 'dog_*', :limit => [0,1]) { |r| r.should == ['louie'] }
411
+ @r.sort('Dogs', :get => 'dog_*', :limit => [0,1], :order => 'desc alpha') { |r| r.should == ['taj'] }
412
+ @r.ping { done }
413
+ end
414
+
415
+ it "should be able to handle array of :get using SORT" do
416
+ @r['dog:1:name'] = 'louie'
417
+ @r['dog:1:breed'] = 'mutt'
418
+ @r.rpush 'dogs', 1
419
+ @r['dog:2:name'] = 'lucy'
420
+ @r['dog:2:breed'] = 'poodle'
421
+ @r.rpush 'dogs', 2
422
+ @r['dog:3:name'] = 'max'
423
+ @r['dog:3:breed'] = 'hound'
424
+ @r.rpush 'dogs', 3
425
+ @r['dog:4:name'] = 'taj'
426
+ @r['dog:4:breed'] = 'terrier'
427
+ @r.rpush 'dogs', 4
428
+ @r.sort('dogs', :get => ['dog:*:name', 'dog:*:breed'], :limit => [0,1]) { |r| r.should == ['louie', 'mutt'] }
429
+ @r.sort('dogs', :get => ['dog:*:name', 'dog:*:breed'], :limit => [0,1], :order => 'desc alpha') { |r| r.should == ['taj', 'terrier'] }
430
+ @r.ping { done }
431
+ end
432
+ #
433
+ it "should be able count the members of a zset" do
434
+ @r.set_add "set", 'key1'
435
+ @r.set_add "set", 'key2'
436
+ @r.zset_add 'zset', 1, 'set'
437
+ @r.zset_count('zset') { |r| r.should == 1 }
438
+ @r.delete('set')
439
+ @r.delete('zset') { done }
440
+ end
441
+ #
442
+ it "should be able add members to a zset" do
443
+ @r.set_add "set", 'key1'
444
+ @r.set_add "set", 'key2'
445
+ @r.zset_add 'zset', 1, 'set'
446
+ @r.zset_range('zset', 0, 1) { |r| r.should == ['set'] }
447
+ @r.zset_count('zset') { |r| r.should == 1 }
448
+ @r.delete('set')
449
+ @r.delete('zset') { done }
450
+ end
451
+ #
452
+ it "should be able delete members to a zset" do
453
+ @r.set_add "set", 'key1'
454
+ @r.set_add "set", 'key2'
455
+ @r.type?('set') { |r| r.should == "set" }
456
+ @r.set_add "set2", 'key3'
457
+ @r.set_add "set2", 'key4'
458
+ @r.type?('set2') { |r| r.should == "set" }
459
+ @r.zset_add 'zset', 1, 'set'
460
+ @r.zset_count('zset') { |r| r.should == 1 }
461
+ @r.zset_add 'zset', 2, 'set2'
462
+ @r.zset_count('zset') { |r| r.should == 2 }
463
+ @r.zset_delete 'zset', 'set'
464
+ @r.zset_count('zset') { |r| r.should == 1 }
465
+ @r.delete('set')
466
+ @r.delete('set2')
467
+ @r.delete('zset') { done }
468
+ end
469
+ #
470
+ it "should be able to get a range of values from a zset" do
471
+ @r.set_add "set", 'key1'
472
+ @r.set_add "set", 'key2'
473
+ @r.set_add "set2", 'key3'
474
+ @r.set_add "set2", 'key4'
475
+ @r.set_add "set3", 'key1'
476
+ @r.type?('set') { |r| r.should == 'set' }
477
+ @r.type?('set2') { |r| r.should == 'set' }
478
+ @r.type?('set3') { |r| r.should == 'set' }
479
+ @r.zset_add 'zset', 1, 'set'
480
+ @r.zset_add 'zset', 2, 'set2'
481
+ @r.zset_add 'zset', 3, 'set3'
482
+ @r.zset_count('zset') { |r| r.should == 3 }
483
+ @r.zset_range('zset', 0, 3) { |r| r.should == ['set', 'set2', 'set3'] }
484
+ @r.delete('set')
485
+ @r.delete('set2')
486
+ @r.delete('set3')
487
+ @r.delete('zset') { done }
488
+ end
489
+ #
490
+ it "should be able to get a reverse range of values from a zset" do
491
+ @r.set_add "set", 'key1'
492
+ @r.set_add "set", 'key2'
493
+ @r.set_add "set2", 'key3'
494
+ @r.set_add "set2", 'key4'
495
+ @r.set_add "set3", 'key1'
496
+ @r.type?('set') { |r| r.should == 'set' }
497
+ @r.type?('set2') { |r| r.should == 'set' }
498
+ @r.type?('set3') { |r| r.should == 'set' }
499
+ @r.zset_add 'zset', 1, 'set'
500
+ @r.zset_add 'zset', 2, 'set2'
501
+ @r.zset_add 'zset', 3, 'set3'
502
+ @r.zset_count('zset') { |r| r.should == 3 }
503
+ @r.zset_reverse_range('zset', 0, 3) { |r| r.should == ['set3', 'set2', 'set'] }
504
+ @r.delete('set')
505
+ @r.delete('set2')
506
+ @r.delete('set3')
507
+ @r.delete('zset') { done }
508
+ end
509
+ #
510
+ it "should be able to get a range by score of values from a zset" do
511
+ @r.set_add "set", 'key1'
512
+ @r.set_add "set", 'key2'
513
+ @r.set_add "set2", 'key3'
514
+ @r.set_add "set2", 'key4'
515
+ @r.set_add "set3", 'key1'
516
+ @r.set_add "set4", 'key4'
517
+ @r.zset_add 'zset', 1, 'set'
518
+ @r.zset_add 'zset', 2, 'set2'
519
+ @r.zset_add 'zset', 3, 'set3'
520
+ @r.zset_add 'zset', 4, 'set4'
521
+ @r.zset_count('zset') { |r| r.should == 4 }
522
+ @r.zset_range_by_score('zset', 2, 3) { |r| r.should == ['set2', 'set3'] }
523
+ @r.delete('set')
524
+ @r.delete('set2')
525
+ @r.delete('set3')
526
+ @r.delete('set4')
527
+ @r.delete('zset') { done }
528
+ end
529
+ #
530
+ it "should be able to get a score for a specific value in a zset (ZSCORE)" do
531
+ @r.zset_add "zset", 23, "value"
532
+ @r.zset_score("zset", "value") { |r| r.should == "23" }
533
+
534
+ @r.zset_score("zset", "value2") { |r| r.should == nil }
535
+ @r.zset_score("unknown_zset", "value") { |r| r.should == nil }
536
+
537
+ @r.delete("zset") { done }
538
+ end
539
+ #
540
+ it "should be able to increment a range score of a zset (ZINCRBY)" do
541
+ # create a new zset
542
+ @r.zset_increment_by "hackers", 1965, "Yukihiro Matsumoto"
543
+ @r.zset_score("hackers", "Yukihiro Matsumoto") { |r| r.should == "1965" }
544
+
545
+ # add a new element
546
+ @r.zset_increment_by "hackers", 1912, "Alan Turing"
547
+ @r.zset_score("hackers", "Alan Turing") { |r| r.should == "1912" }
548
+
549
+ # update the score
550
+ @r.zset_increment_by "hackers", 100, "Alan Turing" # yeah, we are making Turing a bit younger
551
+ @r.zset_score("hackers", "Alan Turing") { |r| r.should == "2012" }
552
+
553
+ # attempt to update a key that's not a zset
554
+ @r["i_am_not_a_zet"] = "value"
555
+ # shouldn't raise error anymore
556
+ @r.zset_incr_by("i_am_not_a_zet", 23, "element") { |r| r.should == nil }
557
+
558
+ @r.delete("hackers")
559
+ @r.delete("i_am_not_a_zet") { done }
560
+ end
561
+ #
562
+ it "should provide info (INFO)" do
563
+ @r.info do |r|
564
+ [: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|
565
+ r.keys.include?(x).should == true
566
+ end
567
+ done
568
+ end
569
+ end
570
+ #
571
+ it "should be able to flush the database (FLUSHDB)" do
572
+ @r['key1'] = 'keyone'
573
+ @r['key2'] = 'keytwo'
574
+ @r.keys('*') { |r| r.sort.should == ['foo', 'key1', 'key2'].sort } #foo from before
575
+ @r.flushdb
576
+ @r.keys('*') { |r| r.should == []; done }
577
+ end
578
+ #
579
+ it "should be able to SELECT database" do
580
+ @r.select(15)
581
+ @r.get('foo') { |r| r.should == nil; done }
582
+ end
583
+ #
584
+ it "should be able to provide the last save time (LASTSAVE)" do
585
+ @r.lastsave do |savetime|
586
+ Time.at(savetime).class.should == Time
587
+ Time.at(savetime).should <= Time.now
588
+ done
589
+ end
590
+ end
591
+
592
+ it "should be able to MGET keys" do
593
+ @r['foo'] = 1000
594
+ @r['bar'] = 2000
595
+ @r.mget('foo', 'bar') { |r| r.should == ['1000', '2000'] }
596
+ @r.mget('foo', 'bar', 'baz') { |r| r.should == ['1000', '2000', nil] }
597
+ @r.ping { done }
598
+ end
599
+
600
+ it "should be able to mapped MGET keys" do
601
+ @r['foo'] = 1000
602
+ @r['bar'] = 2000
603
+ @r.mapped_mget('foo', 'bar') { |r| r.should == { 'foo' => '1000', 'bar' => '2000'} }
604
+ @r.mapped_mget('foo', 'baz', 'bar') { |r| r.should == { 'foo' => '1000', 'bar' => '2000'} }
605
+ @r.ping { done }
606
+ end
607
+
608
+ it "should be able to MSET values" do
609
+ @r.mset :key1 => "value1", :key2 => "value2"
610
+ @r.get('key1') { |r| r.should == "value1" }
611
+ @r.get('key2') { |r| r.should == "value2"; done }
612
+ end
613
+
614
+ it "should be able to MSETNX values" do
615
+ @r.msetnx :keynx1 => "valuenx1", :keynx2 => "valuenx2"
616
+ @r.mget('keynx1', 'keynx2') { |r| r.should == ["valuenx1", "valuenx2"] }
617
+
618
+ @r["keynx1"] = "value1"
619
+ @r["keynx2"] = "value2"
620
+ @r.msetnx :keynx1 => "valuenx1", :keynx2 => "valuenx2"
621
+ @r.mget('keynx1', 'keynx2') { |r| r.should == ["value1", "value2"]; done }
622
+ end
623
+
624
+ it "should bgsave" do
625
+ @r.bgsave do |r|
626
+ ['OK', 'Background saving started'].include?(r).should == true
627
+ done
628
+ end
629
+ end
630
+
631
+ it "should be able to ECHO" do
632
+ @r.echo("message in a bottle\n") { |r| r.should == "message in a bottle\n"; done }
633
+ end
634
+
635
+ # Tests are disabled due uncatchable exceptions. We should use on_error callback,
636
+ # intead of raising exceptions in random places.
637
+ #
638
+ # it "should raise error when invoke MONITOR" do
639
+ # # lambda { @r.monitor }.should.raise
640
+ # done
641
+ # end
642
+ #
643
+ # it "should raise error when invoke SYNC" do
644
+ # # lambda { @r.sync }.should.raise
645
+ # done
646
+ # end
647
+
648
+ it "should run MULTI without a block" do
649
+ @r.multi
650
+ @r.get("key1") { |r| r.should == "QUEUED" }
651
+ @r.discard { done }
652
+ end
653
+
654
+ it "should run MULTI/EXEC with a block" do
655
+ @r.multi do
656
+ @r.set "key1", "value1"
657
+ end
658
+
659
+ @r.get("key1") { |r| r.should == "value1" }
660
+
661
+ begin
662
+ @r.multi do
663
+ @r.set "key2", "value2"
664
+ raise "Some error"
665
+ @r.set "key3", "value3"
666
+ end
667
+ rescue
668
+ end
669
+
670
+ @r.get("key2") { |r| r.should == nil }
671
+ @r.get("key3") { |r| r.should == nil; done}
672
+ end
673
+
674
+ it "should yield the Redis object when using #multi with a block" do
675
+ @r.multi do |multi|
676
+ multi.set "key1", "value1"
677
+ end
678
+
679
+ @r.get("key1") { |r| r.should == "value1"; done }
680
+ end
681
+
682
+ it "can set and get hash values" do
683
+ @r.hset("rush", "signals", "1982") { |r| r.should == true }
684
+ @r.hexists("rush", "signals") { |r| r.should == true }
685
+ @r.hget("rush", "signals") { |r| r.should == "1982"; done }
686
+ end
687
+
688
+ it "can delete hash values" do
689
+ @r.hset("rush", "YYZ", "1981")
690
+ @r.hdel("rush", "YYZ") { |r| r.should == true }
691
+ @r.hexists("rush", "YYZ") { |r| r.should == false; done }
692
+ end
693
+ end
694
+
695
+ # Yup, bacon can't handle nested describe blocks properly
696
+ EM.describe EM::Protocols::Redis, "with some hash values" do
697
+ default_timeout 1
698
+
699
+ before do
700
+ @r = EM::Protocols::Redis.connect :db => 14
701
+ @r.flushdb
702
+ @r['foo'] = 'bar'
703
+ @r.hset("rush", "permanent waves", "1980")
704
+ @r.hset("rush", "moving pictures", "1981")
705
+ @r.hset("rush", "signals", "1982")
706
+ end
707
+
708
+ after { @r.close_connection }
709
+
710
+ it "can get the length of the hash" do
711
+ @r.hlen("rush") { |r| r.should == 3 }
712
+ @r.hlen("yyz") { |r| r.should == 0; done }
713
+ end
714
+
715
+ it "can get the keys and values of the hash" do
716
+ @r.hkeys("rush") { |r| r.should == ["permanent waves", "moving pictures", "signals"] }
717
+ @r.hvals("rush") { |r| r.should == %w[1980 1981 1982] }
718
+ @r.hvals("yyz") { |r| r.should == []; done }
719
+ end
720
+
721
+ it "returns a hash for HGETALL" do
722
+ @r.hgetall("rush") do |r|
723
+ r.should == {
724
+ "permanent waves" => "1980",
725
+ "moving pictures" => "1981",
726
+ "signals" => "1982"
727
+ }
728
+ end
729
+ @r.hgetall("yyz") { |r| r.should == {}; done }
730
+ end
731
+ end
@@ -83,11 +83,11 @@ EM.describe EM::Protocols::Redis do
83
83
  end
84
84
 
85
85
  should "parse an inline error response" do
86
- lambda do
87
- @c.call_command(["blarg"])
88
- @c.receive_data "-FAIL\r\n"
89
- end.should.raise(EM::P::Redis::RedisError)
90
- done
86
+ @c.call_command(["blarg"]) do |resp|
87
+ resp.should == nil
88
+ done
89
+ end
90
+ @c.receive_data "-FAIL\r\n"
91
91
  end
92
92
 
93
93
  should "trigger a given error callback (specified with on_error) for inline error response instead of raising an error" do
@@ -15,6 +15,10 @@ class TestConnection
15
15
  @sent_data ||= ''
16
16
  end
17
17
 
18
+ def maybe_lock
19
+ yield
20
+ end
21
+
18
22
  def initialize
19
23
  super
20
24
  connection_completed
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: superfeedr-em-redis
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 2
9
+ - 7
10
+ version: 0.2.7
5
11
  platform: ruby
6
12
  authors:
7
13
  - Jonathan Broad
@@ -11,50 +17,74 @@ autorequire:
11
17
  bindir: bin
12
18
  cert_chain: []
13
19
 
14
- date: 2010-04-08 00:00:00 +02:00
20
+ date: 2010-06-22 00:00:00 +02:00
15
21
  default_executable:
16
22
  dependencies:
17
23
  - !ruby/object:Gem::Dependency
18
24
  name: eventmachine
19
- type: :runtime
20
- version_requirement:
21
- version_requirements: !ruby/object:Gem::Requirement
25
+ prerelease: false
26
+ requirement: &id001 !ruby/object:Gem::Requirement
27
+ none: false
22
28
  requirements:
23
29
  - - ">="
24
30
  - !ruby/object:Gem::Version
31
+ hash: 59
32
+ segments:
33
+ - 0
34
+ - 12
35
+ - 10
25
36
  version: 0.12.10
26
- version:
37
+ type: :runtime
38
+ version_requirements: *id001
27
39
  - !ruby/object:Gem::Dependency
28
40
  name: bacon
29
- type: :development
30
- version_requirement:
31
- version_requirements: !ruby/object:Gem::Requirement
41
+ prerelease: false
42
+ requirement: &id002 !ruby/object:Gem::Requirement
43
+ none: false
32
44
  requirements:
33
45
  - - ">="
34
46
  - !ruby/object:Gem::Version
47
+ hash: 19
48
+ segments:
49
+ - 1
50
+ - 1
51
+ - 0
35
52
  version: 1.1.0
36
- version:
53
+ type: :development
54
+ version_requirements: *id002
37
55
  - !ruby/object:Gem::Dependency
38
56
  name: em-spec
39
- type: :development
40
- version_requirement:
41
- version_requirements: !ruby/object:Gem::Requirement
57
+ prerelease: false
58
+ requirement: &id003 !ruby/object:Gem::Requirement
59
+ none: false
42
60
  requirements:
43
61
  - - ">="
44
62
  - !ruby/object:Gem::Version
63
+ hash: 21
64
+ segments:
65
+ - 0
66
+ - 2
67
+ - 1
45
68
  version: 0.2.1
46
- version:
69
+ type: :development
70
+ version_requirements: *id003
47
71
  - !ruby/object:Gem::Dependency
48
72
  name: bones
49
- type: :development
50
- version_requirement:
51
- version_requirements: !ruby/object:Gem::Requirement
73
+ prerelease: false
74
+ requirement: &id004 !ruby/object:Gem::Requirement
75
+ none: false
52
76
  requirements:
53
77
  - - ">="
54
78
  - !ruby/object:Gem::Version
79
+ hash: 21
80
+ segments:
81
+ - 3
82
+ - 4
83
+ - 1
55
84
  version: 3.4.1
56
- version:
57
- description: An eventmachine-based implementation of the Redis protocol (forked)
85
+ type: :development
86
+ version_requirements: *id004
87
+ description: An eventmachine-based implementation of the Redis protocol
58
88
  email: stephan@spaceboyz.net
59
89
  executables: []
60
90
 
@@ -64,7 +94,6 @@ extra_rdoc_files:
64
94
  - History.txt
65
95
  - README.rdoc
66
96
  files:
67
- - .gitignore
68
97
  - History.txt
69
98
  - README.rdoc
70
99
  - Rakefile
@@ -73,6 +102,7 @@ files:
73
102
  - lib/em-redis/redis_protocol.rb
74
103
  - spec/live_redis_protocol_spec.rb
75
104
  - spec/redis_commands_spec.rb
105
+ - spec/redis_commands_spec.rb.orig
76
106
  - spec/redis_protocol_spec.rb
77
107
  - spec/test_helper.rb
78
108
  has_rdoc: true
@@ -86,23 +116,29 @@ rdoc_options:
86
116
  require_paths:
87
117
  - lib
88
118
  required_ruby_version: !ruby/object:Gem::Requirement
119
+ none: false
89
120
  requirements:
90
121
  - - ">="
91
122
  - !ruby/object:Gem::Version
123
+ hash: 3
124
+ segments:
125
+ - 0
92
126
  version: "0"
93
- version:
94
127
  required_rubygems_version: !ruby/object:Gem::Requirement
128
+ none: false
95
129
  requirements:
96
130
  - - ">="
97
131
  - !ruby/object:Gem::Version
132
+ hash: 3
133
+ segments:
134
+ - 0
98
135
  version: "0"
99
- version:
100
136
  requirements: []
101
137
 
102
138
  rubyforge_project: superfeedr-em-redis
103
- rubygems_version: 1.3.5
139
+ rubygems_version: 1.3.7
104
140
  signing_key:
105
141
  specification_version: 3
106
- summary: An eventmachine-based implementation of the Redis protocol (forked)
142
+ summary: An eventmachine-based implementation of the Redis protocol
107
143
  test_files: []
108
144
 
data/.gitignore DELETED
@@ -1,2 +0,0 @@
1
- .DS_Store
2
- pkg