redis 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/redis.rb +2 -1
- data/lib/redis/client.rb +60 -30
- data/lib/redis/subscribe.rb +14 -0
- metadata +3 -2
data/lib/redis.rb
CHANGED
data/lib/redis/client.rb
CHANGED
@@ -124,6 +124,11 @@ class Redis
|
|
124
124
|
"sync" => true
|
125
125
|
}
|
126
126
|
|
127
|
+
BLOCKING_COMMANDS = {
|
128
|
+
"blpop" => true,
|
129
|
+
"brpop" => true
|
130
|
+
}
|
131
|
+
|
127
132
|
def initialize(options = {})
|
128
133
|
@host = options[:host] || '127.0.0.1'
|
129
134
|
@port = (options[:port] || 6379).to_i
|
@@ -265,29 +270,39 @@ class Redis
|
|
265
270
|
end
|
266
271
|
|
267
272
|
def subscribe(*classes)
|
268
|
-
#
|
269
|
-
#
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
raise "
|
274
|
-
elsif @pubsub
|
275
|
-
|
276
|
-
elsif @pubsub == true
|
277
|
-
# This is a nested subscribe call without a block given.
|
278
|
-
# We just need to send the subscribe command and return asap.
|
273
|
+
# Top-level `subscribe` MUST be called with a block,
|
274
|
+
# nested `subscribe` MUST NOT be called with a block
|
275
|
+
if !@pubsub && !block_given?
|
276
|
+
raise "Top-level subscribe requires a block"
|
277
|
+
elsif @pubsub == true && block_given?
|
278
|
+
raise "Nested subscribe does not take a block"
|
279
|
+
elsif @pubsub
|
280
|
+
# If we're already pubsub'ing, just subscribe us to some more classes
|
279
281
|
call_command [:subscribe,*classes]
|
280
282
|
return true
|
281
283
|
end
|
284
|
+
|
282
285
|
@pubsub = true
|
283
286
|
call_command [:subscribe,*classes]
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
287
|
+
sub = Subscription.new
|
288
|
+
yield(sub)
|
289
|
+
begin
|
290
|
+
while true
|
291
|
+
type, *reply = read_reply # type, [class,data]
|
292
|
+
case type
|
293
|
+
when 'subscribe','unsubscribe'
|
294
|
+
sub.send(type) && sub.send(type).call(reply[0])
|
295
|
+
when 'message'
|
296
|
+
sub.send(type) && sub.send(type).call(reply[0],reply[1])
|
297
|
+
end
|
298
|
+
break if type == 'unsubscribe' && reply[1] == 0
|
299
|
+
end
|
300
|
+
rescue RuntimeError
|
301
|
+
call_command [:unsubscribe]
|
302
|
+
raise
|
303
|
+
ensure
|
304
|
+
@pubsub = false
|
289
305
|
end
|
290
|
-
@pubsub = false
|
291
306
|
end
|
292
307
|
|
293
308
|
def unsubscribe(*classes)
|
@@ -295,8 +310,6 @@ class Redis
|
|
295
310
|
return true
|
296
311
|
end
|
297
312
|
|
298
|
-
protected
|
299
|
-
|
300
313
|
def call_command(argv)
|
301
314
|
log(argv.inspect, :debug)
|
302
315
|
|
@@ -339,16 +352,7 @@ class Redis
|
|
339
352
|
# to make sure a blocking read will return after the specified number
|
340
353
|
# of seconds. This hack is from memcached ruby client.
|
341
354
|
if timeout
|
342
|
-
|
343
|
-
usecs = Integer((timeout - secs) * 1_000_000)
|
344
|
-
optval = [secs, usecs].pack("l_2")
|
345
|
-
begin
|
346
|
-
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval
|
347
|
-
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval
|
348
|
-
rescue Exception => ex
|
349
|
-
# Solaris, for one, does not like/support socket timeouts.
|
350
|
-
log("Unable to use raw socket timeouts: #{ex.class.name}: #{ex.message}")
|
351
|
-
end
|
355
|
+
set_socket_timeout(sock, timeout)
|
352
356
|
end
|
353
357
|
sock
|
354
358
|
end
|
@@ -406,7 +410,15 @@ class Redis
|
|
406
410
|
return true
|
407
411
|
end
|
408
412
|
# The normal command execution is reading and processing the reply.
|
409
|
-
results = maybe_lock
|
413
|
+
results = maybe_lock do
|
414
|
+
begin
|
415
|
+
set_socket_timeout(@sock, 0) if requires_timeout_reset?(argvv[0][0].to_s)
|
416
|
+
process_command(command, argvv)
|
417
|
+
ensure
|
418
|
+
set_socket_timeout(@sock, @timeout) if requires_timeout_reset?(argvv[0][0].to_s)
|
419
|
+
end
|
420
|
+
end
|
421
|
+
|
410
422
|
return pipeline ? results : results[0]
|
411
423
|
end
|
412
424
|
|
@@ -478,5 +490,23 @@ class Redis
|
|
478
490
|
def deprecated(old, new, trace = caller[0])
|
479
491
|
$stderr.puts "\nRedis: The method #{old} is deprecated. Use #{new} instead (in #{trace})"
|
480
492
|
end
|
493
|
+
|
494
|
+
def requires_timeout_reset?(command)
|
495
|
+
BLOCKING_COMMANDS[command] && @timeout
|
496
|
+
end
|
497
|
+
|
498
|
+
def set_socket_timeout(sock, timeout)
|
499
|
+
secs = Integer(timeout)
|
500
|
+
usecs = Integer((timeout - secs) * 1_000_000)
|
501
|
+
optval = [secs, usecs].pack("l_2")
|
502
|
+
begin
|
503
|
+
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_RCVTIMEO, optval
|
504
|
+
sock.setsockopt Socket::SOL_SOCKET, Socket::SO_SNDTIMEO, optval
|
505
|
+
rescue Exception => ex
|
506
|
+
# Solaris, for one, does not like/support socket timeouts.
|
507
|
+
log("Unable to use raw socket timeouts: #{ex.class.name}: #{ex.message}")
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
481
511
|
end
|
482
512
|
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class Subscription
|
2
|
+
def subscribe(&block)
|
3
|
+
if block_given? then @subscribe = block else @subscribe end
|
4
|
+
end
|
5
|
+
|
6
|
+
def unsubscribe(&block)
|
7
|
+
if block_given? then @unsubscribe = block else @unsubscribe end
|
8
|
+
end
|
9
|
+
|
10
|
+
def message(&block)
|
11
|
+
if block_given? then @message = block else @message end
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 1.0.
|
8
|
+
- 1
|
9
|
+
version: 1.0.1
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Ezra Zygmuntowicz
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- lib/redis/hash_ring.rb
|
53
53
|
- lib/redis/pipeline.rb
|
54
54
|
- lib/redis/raketasks.rb
|
55
|
+
- lib/redis/subscribe.rb
|
55
56
|
- lib/redis.rb
|
56
57
|
- tasks/redis.tasks.rb
|
57
58
|
has_rdoc: true
|