redis 1.0.0 → 1.0.1
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/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
|