superfeedr-em-redis 0.2.6 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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