redpack 1.0.3 → 1.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -19,126 +19,126 @@
19
19
  module RedPack
20
20
 
21
21
  class Client
22
- def initialize(name, redis_options = {:host => 'localhost'})
23
- @timeout = 10
24
- @seqid = 0
25
- @reqtable = {}
26
- @transport = RedisClientTransport.new(self, redis_options, name)
27
- end
28
- attr_accessor :timeout
22
+ def initialize(name, redis_options = {:host => 'localhost'})
23
+ @timeout = 10
24
+ @seqid = 0
25
+ @reqtable = {}
26
+ @transport = RedisClientTransport.new(self, redis_options, name)
27
+ end
28
+ attr_accessor :timeout
29
+
30
+ # call-seq:
31
+ # notify(symbol, *args) -> nil
32
+ #
33
+ # Calls remote method with NOTIFY protocol.
34
+ # It doesn't require server to return results.
35
+ # This method is non-blocking and returns nil.
36
+ def notify(method, *args)
37
+ send_notify(method, args)
38
+ nil
39
+ end
29
40
 
30
- # call-seq:
31
- # notify(symbol, *args) -> nil
32
- #
33
- # Calls remote method with NOTIFY protocol.
34
- # It doesn't require server to return results.
35
- # This method is non-blocking and returns nil.
36
- def notify(method, *args)
37
- send_notify(method, args)
38
- nil
39
- end
40
-
41
- # call code like this for sync calls:
42
- # counter = client.increment_remote_counter_sync(1, 2, 3)
43
- #
44
- # call code like this for async non-blocking calls:
45
- # client.increment_remote_counter_async(1, 2, 3) do |error, result|
46
- # if error
47
- # raise "we got an error"
48
- # else
49
- # counter = result
50
- # end
51
- # end
52
- def method_missing(method, *args, &block)
53
- method_name = method.to_s
54
- sync = method_name.end_with?("_sync")
55
- async = method_name.end_with?("_async")
41
+ # call code like this for sync calls:
42
+ # counter = client.increment_remote_counter_sync(1, 2, 3)
43
+ #
44
+ # call code like this for async non-blocking calls:
45
+ # client.increment_remote_counter_async(1, 2, 3) do |error, result|
46
+ # if error
47
+ # raise "we got an error"
48
+ # else
49
+ # counter = result
50
+ # end
51
+ # end
52
+ def method_missing(method, *args, &block)
53
+ method_name = method.to_s
54
+ sync = method_name.end_with?("_sync")
55
+ async = method_name.end_with?("_async")
56
56
  if sync || async
57
- method_name.gsub!(/_sync$/, '') if sync
58
- method_name.gsub!(/_async$/, '') if async
59
- future = send_request(method_name, args, !!sync)
60
- future.attach_callback(block) if block
61
- if sync
62
- @transport.listen_for_return_sync
63
- future.get
64
- if future.error
65
- raise error
66
- else
67
- return future.result
68
- end
69
- elsif async
70
- @transport.listen_for_return_async
71
- return future
57
+ method_name.gsub!(/_sync$/, '') if sync
58
+ method_name.gsub!(/_async$/, '') if async
59
+ future = send_request(method_name, args, !!sync)
60
+ future.attach_callback(block) if block
61
+ if sync
62
+ @transport.listen_for_return_sync
63
+ future.get
64
+ if future.error
65
+ raise error
66
+ else
67
+ return future.result
68
+ end
69
+ elsif async
70
+ @transport.listen_for_return_async
71
+ return future
72
72
  end
73
73
  else
74
74
  super
75
75
  end
76
76
  end
77
-
78
77
 
79
- # Closes underlaying Transport and destroy resources.
80
- def close
81
- @timer.detach if @timer.attached?
82
- @reqtable = {}
83
- @transport.close
84
- @seqid = 0
85
- self
86
- end
87
-
88
- # from ClientTransport
89
- def on_response(sock, msgid, error, result) #:nodoc:
90
- if future = @reqtable.delete(msgid)
91
- future.set_result(error, result)
92
- end
93
- end
94
78
 
95
- # from ClientTransport
96
- def on_connect_failed #:nodoc:
97
- @reqtable.reject! {|msgid, future|
98
- begin
99
- future.set_result ConnectError.new, nil
100
- rescue
101
- end
102
- true
103
- }
104
- nil
105
- end
79
+ # Closes underlaying Transport and destroy resources.
80
+ def close
81
+ @timer.detach if @timer.attached?
82
+ @reqtable = {}
83
+ @transport.close
84
+ @seqid = 0
85
+ self
86
+ end
106
87
 
107
- # from Client, SessionPool
108
- def step_timeout #:nodoc:
109
- timedout = []
110
- @reqtable.reject! {|msgid, future|
111
- if future.step_timeout
112
- timedout.push(future)
113
- true
114
- end
115
- }
116
- timedout.each {|future|
117
- begin
118
- future.set_result TimeoutError.new, nil
119
- rescue
120
- end
121
- }
122
- !@reqtable.empty?
123
- end
88
+ # from ClientTransport
89
+ def on_response(sock, msgid, error, result) #:nodoc:
90
+ if future = @reqtable.delete(msgid)
91
+ future.set_result(error, result)
92
+ end
93
+ end
124
94
 
95
+ # from ClientTransport
96
+ def on_connect_failed #:nodoc:
97
+ @reqtable.reject! {|msgid, future|
98
+ begin
99
+ future.set_result ConnectError.new, nil
100
+ rescue
101
+ end
102
+ true
103
+ }
104
+ nil
105
+ end
106
+
107
+ # from Client, SessionPool
108
+ def step_timeout #:nodoc:
109
+ timedout = []
110
+ @reqtable.reject! {|msgid, future|
111
+ if future.step_timeout
112
+ timedout.push(future)
113
+ true
114
+ end
115
+ }
116
+ timedout.each {|future|
117
+ begin
118
+ future.set_result TimeoutError.new, nil
119
+ rescue
120
+ end
121
+ }
122
+ !@reqtable.empty?
123
+ end
125
124
 
126
- private
127
- def send_request(method, param, sync = false)
128
- method = method.to_s
129
- msgid = @seqid
130
- @seqid += 1; if @seqid >= 1<<31 then @seqid = 0 end
131
- data = [REQUEST, msgid, method, param]
132
- @transport.send_data(data, msgid, sync)
133
- @reqtable[msgid] = Future.new(self)
134
- end
135
125
 
136
- def send_notify(method, param)
137
- method = method.to_s
138
- data = [NOTIFY, method, param]
139
- @transport.send_data(data, nil)
140
- nil
141
- end
126
+ private
127
+ def send_request(method, param, sync = false)
128
+ method = method.to_s
129
+ msgid = @seqid
130
+ @seqid += 1; if @seqid >= 1<<31 then @seqid = 0 end
131
+ data = [REQUEST, msgid, method, param]
132
+ @transport.send_data(data, msgid, sync)
133
+ @reqtable[msgid] = Future.new(self)
134
+ end
135
+
136
+ def send_notify(method, param)
137
+ method = method.to_s
138
+ data = [NOTIFY, method, param]
139
+ @transport.send_data(data, nil)
140
+ nil
141
+ end
142
142
  end
143
143
 
144
144
  end
@@ -23,79 +23,79 @@ module RedPack
23
23
  # because it is not yet received.
24
24
  # You can wait and get the result with get method.
25
25
  class Future
26
- def initialize(session, callback = nil) #:nodoc:
27
- @timeout = session.timeout
28
- @callback_handler = callback
29
- @error_handler = nil
30
- @result_handler = nil
31
- @set = false
32
- @error = nil
33
- @result = nil
34
- end
35
- attr_accessor :result, :error
26
+ def initialize(session, callback = nil) #:nodoc:
27
+ @timeout = session.timeout
28
+ @callback_handler = callback
29
+ @error_handler = nil
30
+ @result_handler = nil
31
+ @set = false
32
+ @error = nil
33
+ @result = nil
34
+ end
35
+ attr_accessor :result, :error
36
36
 
37
- # Wait for receiving result of remote procedure call and returns its result.
38
- # If the remote method raises error, then this method raises RemoteError.
39
- # If the remote procedure call failed with timeout, this method raises TimeoutError.
40
- # Otherwise this method returns the result of remote method.
41
- def get
42
- join
43
- if error.nil?
44
- if @result_handler
45
- return @result_handler.call(@result)
46
- else
47
- return @result
48
- end
49
- end
50
- if @error_handler
51
- return @error_handler.call(self)
52
- else
53
- raise @error if @error.is_a?(Error)
54
- raise RemoteError.new(@error, @result)
55
- end
56
- end
37
+ # Wait for receiving result of remote procedure call and returns its result.
38
+ # If the remote method raises error, then this method raises RemoteError.
39
+ # If the remote procedure call failed with timeout, this method raises TimeoutError.
40
+ # Otherwise this method returns the result of remote method.
41
+ def get
42
+ join
43
+ if error.nil?
44
+ if @result_handler
45
+ return @result_handler.call(@result)
46
+ else
47
+ return @result
48
+ end
49
+ end
50
+ if @error_handler
51
+ return @error_handler.call(self)
52
+ else
53
+ raise @error if @error.is_a?(Error)
54
+ raise RemoteError.new(@error, @result)
55
+ end
56
+ end
57
57
 
58
- # Wait for receiving result of remote procedure call.
59
- # This method returns self.
60
- # If a callback method is attached, it will be called.
61
- def join
62
- until @set
63
- sleep(0.0001)
64
- end
65
- self
66
- end
58
+ # Wait for receiving result of remote procedure call.
59
+ # This method returns self.
60
+ # If a callback method is attached, it will be called.
61
+ def join
62
+ until @set
63
+ sleep(0.0001)
64
+ end
65
+ self
66
+ end
67
67
 
68
- # call-seq:
69
- # attach_callback {|future| }
70
- #
71
- # Attaches a callback method that is called when the result of remote method is received.
72
- def attach_callback(proc = nil, &block)
73
- @callback_handler = proc || block
74
- end
68
+ # call-seq:
69
+ # attach_callback {|future| }
70
+ #
71
+ # Attaches a callback method that is called when the result of remote method is received.
72
+ def attach_callback(proc = nil, &block)
73
+ @callback_handler = proc || block
74
+ end
75
75
 
76
- # For IDL
77
- def attach_error_handler(proc = nil, &block) #:nodoc:
78
- @error_handler = proc || block
79
- end
76
+ # For IDL
77
+ def attach_error_handler(proc = nil, &block) #:nodoc:
78
+ @error_handler = proc || block
79
+ end
80
80
 
81
- # For IDL
82
- def attach_result_handler(proc = nil, &block) #:nodoc:
83
- @result_handler = proc || block
84
- end
81
+ # For IDL
82
+ def attach_result_handler(proc = nil, &block) #:nodoc:
83
+ @result_handler = proc || block
84
+ end
85
85
 
86
- def set_result(err, res) #:nodoc:
87
- @error = err
88
- @result = res
89
- if @callback_handler
90
- if @callback_handler.arity == 2
91
- # FIXME backward compatibility
92
- @callback_handler.call(error, result)
93
- else
94
- @callback_handler.call(self)
95
- end
96
- end
97
- @set = true
98
- end
86
+ def set_result(err, res) #:nodoc:
87
+ @error = err
88
+ @result = res
89
+ if @callback_handler
90
+ if @callback_handler.arity == 2
91
+ # FIXME backward compatibility
92
+ @callback_handler.call(error, result)
93
+ else
94
+ @callback_handler.call(self)
95
+ end
96
+ end
97
+ @set = true
98
+ end
99
99
  end
100
100
 
101
101
  end
@@ -37,9 +37,9 @@ class RedisClientTransport
37
37
  # Pass in {:ignore_return_value => true} as part of the redis_options so that the server doesn't put the return
38
38
  # object in a queue. This is useful if you're doing call_async and never care about the return value. It saves
39
39
  # Redis from adding a key/list pair. A synchronous call will result in an immediate timeout exception.
40
- def initialize(client, redis_options, name)
41
- @client = client
42
- @queue_name = "redpack_request_queue:#{name}"
40
+ def initialize(client, redis_options, name)
41
+ @client = client
42
+ @queue_name = "redpack_request_queue:#{name}"
43
43
  @ignore_return_value = !!redis_options.delete(:ignore_return_value)
44
44
  if @ignore_return_value
45
45
  @client.timeout = 0
@@ -50,12 +50,12 @@ class RedisClientTransport
50
50
  @redis_options = redis_options
51
51
  @redis = Redis.new(redis_options)
52
52
 
53
- # assign a unique client key for this instance which will be used for return values
54
- @identifier = @redis.incr("redpack_response_queue_index")
55
- @return_queue_name = "redpack_response_queue:#{@identifier}"
56
- @unprocessed_requests_name = "#{@return_queue_name}:unprocessed"
57
- @pool = 0
58
- end
53
+ # assign a unique client key for this instance which will be used for return values
54
+ @identifier = @redis.incr("redpack_response_queue_index")
55
+ @return_queue_name = "redpack_response_queue:#{@identifier}"
56
+ @unprocessed_requests_name = "#{@return_queue_name}:unprocessed"
57
+ @pool = 0
58
+ end
59
59
 
60
60
  def process_data(data)
61
61
  # puts "done waiting for #{@return_queue_name}"
@@ -77,26 +77,25 @@ class RedisClientTransport
77
77
  end
78
78
  end
79
79
 
80
- def listen_for_return_sync
80
+ def listen_for_return_sync
81
81
  process_data(@redis.blpop(@return_queue_name, 0))
82
82
  end
83
83
 
84
- def listen_for_return_async
85
- Thread.new do
84
+ def listen_for_return_async
85
+ Thread.new do
86
86
  unless @ignore_return_value
87
- EM.run do
88
- redis = EventMachine::Protocols::Redis.connect(@redis_options)
89
- # puts "waiting for #{@return_queue_name}"
90
- redis.blpop(@return_queue_name, 0) do |data|
91
- process_data(data)
92
- end
93
- end
94
- end
87
+ EM.run do
88
+ redis = EventMachine::Protocols::Redis.connect(@redis_options)
89
+ redis.blpop(@return_queue_name, 0) do |data|
90
+ process_data(data)
91
+ end
92
+ end
93
+ end
95
94
  end
96
95
  end
97
96
 
98
- def redis_push(msgpack_data, msgid = nil)
99
- if msgid
97
+ def redis_push(msgpack_data, msgid = nil)
98
+ if msgid
100
99
  @redis.multi
101
100
  # puts "setting key in #{@unprocessed_requests_name}"
102
101
  @redis.hset(@unprocessed_requests_name, msgid.to_s, msgpack_data)
@@ -108,89 +107,89 @@ class RedisClientTransport
108
107
  end
109
108
  end
110
109
 
111
- def send_data(data, msgid = nil, sync = false)
112
- if sync
110
+ def send_data(data, msgid = nil, sync = false)
111
+ if @ignore_return_value
112
+ redis_push(BSON.serialize({:data => data}), msgid)
113
+ else
113
114
  redis_push(BSON.serialize({:data => data, :return => @return_queue_name}), msgid)
114
- elsif @ignore_return_value || !sync
115
- redis_push(BSON.serialize({:data => data}), msgid)
116
115
  end
117
- end
116
+ end
118
117
 
119
- def close
120
- self
121
- end
118
+ def close
119
+ self
120
+ end
122
121
 
123
- def on_connect(sock)
124
- end
122
+ def on_connect(sock)
123
+ end
125
124
 
126
- def on_response(msgid, error, result)
127
- @client.on_response(self, msgid, error, result)
128
- end
125
+ def on_response(msgid, error, result)
126
+ @client.on_response(self, msgid, error, result)
127
+ end
129
128
 
130
- def on_connect_failed(sock)
131
- end
129
+ def on_connect_failed(sock)
130
+ end
132
131
 
133
- def on_close(sock)
134
- end
132
+ def on_close(sock)
133
+ end
135
134
  end
136
135
 
137
136
  class RedisServerTransport
138
137
  include Util
139
-
140
- def initialize(name, redis_options = {})
141
- @ignore_nil_returns = !!redis_options.delete(:ignore_nil_returns)
138
+
139
+ def initialize(name, redis_options = {})
140
+ @ignore_nil_returns = !!redis_options.delete(:ignore_nil_returns)
142
141
  @redis = Redis.new(redis_options)
143
- @queue_name = "redpack_request_queue:#{name}"
144
- @timeout_mechanism = redis_options[:timeout_mechanism]
145
- end
142
+ @queue_name = "redpack_request_queue:#{name}"
143
+ @timeout_mechanism = redis_options[:timeout_mechanism]
144
+ end
146
145
 
147
- # ServerTransport interface
148
- def listen(server)
149
- @server = server
146
+ # ServerTransport interface
147
+ def listen(server)
148
+ @server = server
150
149
  loop do
151
150
  begin
152
151
  # puts "listening to #{@queue_name}"
153
152
  data = @redis.blpop(@queue_name, 0)
154
153
  # puts "popped item off of #{@queue_name}"
155
- if data && data[1]
156
- redis_packet = BSON.deserialize(data[1])
157
- if redis_packet["data"]
158
- @return_queue_name = redis_packet["return"]
159
- @unprocessed_requests_name = "#{@return_queue_name}:unprocessed"
160
- msg = redis_packet["data"]
161
- case msg[0]
162
- when REQUEST
163
- @server.on_request(self, msg[1], msg[2], msg[3])
164
- when RESPONSE
165
- puts "response message on server session"
166
- when NOTIFY
167
- @server.on_notify(msg[1], msg[2])
168
- else
169
- puts "unknown message type #{msg[0]}"
170
- end
171
- end
172
- end
173
- rescue => e
174
- # probably timed out
175
- p e
176
- @timeout_mechanism.call if @timeout_mechanism
177
- end
154
+ if data && data[1]
155
+ redis_packet = BSON.deserialize(data[1])
156
+ if redis_packet["data"]
157
+ @return_queue_name = redis_packet["return"]
158
+ @unprocessed_requests_name = "#{@return_queue_name}:unprocessed"
159
+ msg = redis_packet["data"]
160
+ case msg[0]
161
+ when REQUEST
162
+ @server.on_request(self, msg[1], msg[2], msg[3])
163
+ when RESPONSE
164
+ puts "response message on server session"
165
+ when NOTIFY
166
+ @server.on_notify(msg[1], msg[2])
167
+ else
168
+ puts "unknown message type #{msg[0]}"
169
+ end
170
+ end
171
+ end
172
+ rescue => e
173
+ # probably timed out
174
+ p e
175
+ @timeout_mechanism.call if @timeout_mechanism
176
+ end
178
177
  end
179
- end
180
-
181
- def finish(msgid)
182
- # puts "removing key from #{@unprocessed_requests_name}"
183
- @redis.hdel(@unprocessed_requests_name, msgid.to_s)
184
178
  end
185
179
 
186
- def send_data(data)
187
- # puts "putting data on #{@return_queue_name}"
180
+ def finish(msgid)
181
+ # puts "removing key from #{@unprocessed_requests_name}"
182
+ @redis.hdel(@unprocessed_requests_name, msgid.to_s)
183
+ end
184
+
185
+ def send_data(data)
186
+ # puts "putting data on #{@return_queue_name}"
188
187
  @redis.rpush(@return_queue_name, BSON.serialize({:data => data})) if @return_queue_name
189
188
  end
190
189
 
191
- # ServerTransport interface
192
- def close
193
- end
190
+ # ServerTransport interface
191
+ def close
192
+ end
194
193
  end
195
194
 
196
- end
195
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 1
7
7
  - 0
8
- - 3
9
- version: 1.0.3
8
+ - 4
9
+ version: 1.0.4
10
10
  platform: ruby
11
11
  authors:
12
12
  - Dean Mao
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-01-19 00:00:00 -08:00
17
+ date: 2011-02-01 00:00:00 -08:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency