forked from AE9RB/ruby-redis
/
synchrony.rb
58 lines (47 loc) · 1.22 KB
/
synchrony.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
require File.expand_path '../redis', File.dirname(__FILE__)
require 'fiber'
class Redis
# Compatible with em-synchrony
# Not included by default, use:
# require 'redis/synchrony'
class Synchrony
def self.sync(df)
f = Fiber.current
xback = proc {|r|
if f == Fiber.current
return r
else
f.resume r
end
}
df.callback &xback
df.errback &xback
Fiber.yield
end
attr_accessor :timeout
def initialize redis
@redis = redis
@timeout = nil
end
def pubsub_callback
raise 'only available async'
end
def method_missing method, *args, &block
result = @redis.send method, *args, &block
if result.respond_to? :callback and result.respond_to? :errback
result.timeout @timeout if @timeout and result.respond_to? :timeout
result = self.class.sync result
raise result if Exception === result
end
result
end
end
def self.synchrony blk=nil, tail=nil, &block
blk ||= block
context = Proc.new { Fiber.new { blk.call }.resume }
EventMachine.run(context, tail)
end
def synchrony
@synchrony ||= Synchrony.new self
end
end