msgpack-rpc 0.4.0 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,303 @@
1
+ #
2
+ # MessagePack-RPC for Ruby
3
+ #
4
+ # Copyright (C) 2010 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module MessagePack
19
+ module RPC
20
+
21
+
22
+ class Error < StandardError
23
+ end
24
+
25
+ class RPCError < Error
26
+ def initialize(msg)
27
+ super(msg)
28
+ end
29
+ end
30
+
31
+ class RemoteError < RPCError
32
+ def initialize(msg, result = nil)
33
+ super(msg)
34
+ @result = result
35
+ end
36
+ attr_reader :result
37
+ end
38
+
39
+ class TimeoutError < Error
40
+ def initialize(msg = "request timed out")
41
+ super
42
+ end
43
+ end
44
+
45
+ class ConnectError < TimeoutError
46
+ def initialize(msg = "connect failed")
47
+ super
48
+ end
49
+ end
50
+
51
+
52
+
53
+ ##
54
+ ## MessagePack-RPC Exception
55
+ ##
56
+ #
57
+ # MessagePack-RPC Transport Layer
58
+ # [int, msgid, object, object] を転送する
59
+ # これを転送できない場合はTransportError
60
+ #
61
+ # メッセージ到達 1
62
+ # ハンドラ到達 2
63
+ # リトライ推奨 r
64
+ #
65
+ # RPCError
66
+ # |
67
+ # +-- TimeoutError : [?]
68
+ # |
69
+ # +-- TransportError : []
70
+ # | |
71
+ # | +-- NetworkUnreachableError
72
+ # | |
73
+ # | +-- ConnectionRefusedError
74
+ # | |
75
+ # | +-- ConnectionTimeoutError
76
+ # | |
77
+ # | +-- MalformedMessageError
78
+ # | |
79
+ # | +-- ConnectionClosedError
80
+ # |
81
+ # +-- CallError : [1]
82
+ # | |
83
+ # | +-- NoMethodError
84
+ # | |
85
+ # | +-- ArgumentError
86
+ # |
87
+ # +-- ServerError : [1, 2?, r]
88
+ # | |
89
+ # | +-- ServerBusyError
90
+ # | |
91
+ # | +-- GatewayError
92
+ # | |
93
+ # | +-- GatewayTimeoutError
94
+ # |
95
+ # +-- RemoteError : [1, 2]
96
+ # |
97
+ # +-- RemoteRuntimeError
98
+ # |
99
+ # +-- (user-defined errors)
100
+ #
101
+ ##
102
+ ## MessagePack-RPC Exception
103
+ ##
104
+ #
105
+ # RPCError
106
+ # |
107
+ # +-- TimeoutError : 到達=不明 リトライ=アプリ判断
108
+ # |
109
+ # +-- TransportError : 到達=していない リトライ=非推奨
110
+ # | |
111
+ # | +-- NetworkUnreachableError
112
+ # | |
113
+ # | +-- ConnectionRefusedError
114
+ # | |
115
+ # | +-- ConnectionTimeoutError
116
+ # |
117
+ # +-- SessionError : 到達=した リトライ=非推奨
118
+ # | |
119
+ # | +-- MessageRefusedError
120
+ # | | |
121
+ # | | +-- MessageTooLargeError
122
+ # | |
123
+ # | +-- NoMethodError
124
+ # | |
125
+ # | +-- ArgumentError
126
+ # |
127
+ # +-- ServerError : 到達=した リトライ=推奨
128
+ # | |
129
+ # | +-- ServerBusyError
130
+ # |
131
+ # +-- RemoteError
132
+ # |
133
+ # +-- RemoteRuntimeError
134
+ # |
135
+ # +-- (user-defined errors)
136
+ #
137
+ #
138
+ ##
139
+ ## MessagePack-RPC Exception
140
+ ##
141
+ #
142
+ # RPCError
143
+ # |
144
+ # +-- TimeoutError
145
+ # |
146
+ # +-- ClientError
147
+ # | |
148
+ # | +-- TransportError
149
+ # | | |
150
+ # | | +-- NetworkUnreachableError
151
+ # | | |
152
+ # | | +-- ConnectionRefusedError
153
+ # | | |
154
+ # | | +-- ConnectionTimeoutError
155
+ # | | |
156
+ # | | +-- MessageTooLargeError
157
+ # | |
158
+ # | +-- SessionError
159
+ # | |
160
+ # | +-- NoMethodError
161
+ # | |
162
+ # | +-- ArgumentError
163
+ # |
164
+ # +-- ServerError
165
+ # | |
166
+ # | +-- ServerBusyError
167
+ # |
168
+ # +-- RemoteError
169
+ # |
170
+ # +-- (Remote)RuntimeError
171
+ # |
172
+ # +-- (user-defined errors)
173
+ #
174
+
175
+ =begin
176
+ class Error < StandardError
177
+ end
178
+
179
+ class RPCError < Error
180
+ def initialize(msg, code)
181
+ super(msg)
182
+ @code = code
183
+ end
184
+ attr_reader :code
185
+ end
186
+
187
+
188
+ class TimeoutError < RPCError
189
+ CODE = ".TimeoutError"
190
+ def initialize(msg = "request timed out")
191
+ super(msg, CODE)
192
+ end
193
+ end
194
+
195
+
196
+ class ClientError < RPCError
197
+ CODE = ".ClientError"
198
+ def initialize(msg, code)
199
+ super(msg, code)
200
+ end
201
+ end
202
+
203
+
204
+ class TransportError < ClientError
205
+ CODE = ".TransportError"
206
+ def initialize(msg, code = CODE)
207
+ super(msg, CODE)
208
+ end
209
+ end
210
+
211
+ class NetworkUnreachableError < TransportError
212
+ CODE = ".NetworkUnreachableError"
213
+ def initialize(msg = "network unreachable")
214
+ super(msg, CODE)
215
+ end
216
+ end
217
+
218
+ class ConnectionRefusedError < TransportError
219
+ CODE = -52
220
+ def initialize(msg = "connection refused")
221
+ super(msg, CODE)
222
+ end
223
+ end
224
+
225
+ class ConnectionTimeoutError < TransportError
226
+ CODE = -53
227
+ def initialize(msg = "connection timed out")
228
+ super(msg, CODE)
229
+ end
230
+ end
231
+
232
+
233
+ class MessageRefusedError < ClientError
234
+ CODE = -40
235
+ def initialize(msg = "broken message", code = CODE)
236
+ super(msg, code)
237
+ end
238
+ end
239
+
240
+ class MessageTooLargeError < MessageRefusedError
241
+ CODE = -41
242
+ def initialize(msg = "messge too large")
243
+ super(msg, CODE)
244
+ end
245
+ end
246
+
247
+
248
+ class CallError < ClientError
249
+ CODE = -20
250
+ def initialize(msg, code = CODE)
251
+ super(msg, code)
252
+ end
253
+ end
254
+
255
+ class NoMethodError < CallError
256
+ CODE = -21
257
+ def initialize(msg = "method not found")
258
+ super(msg, CODE)
259
+ end
260
+ end
261
+
262
+ class ArgumentError < NoMethodError
263
+ CODE = -22
264
+ def initialize(msg = "invalid argument")
265
+ super(msg, CODE)
266
+ end
267
+ end
268
+
269
+
270
+ class ServerError < RPCError
271
+ CODE = -30
272
+ def initialize(msg, code = CODE)
273
+ super(msg, code)
274
+ end
275
+ end
276
+
277
+ class ServerBusyError < ServerError
278
+ CODE = -31
279
+ def initialize(msg = "server temporally busy")
280
+ super(msg, CODE)
281
+ end
282
+ end
283
+
284
+
285
+ class RemoteError < RPCError
286
+ def initialize(msg, code, result = nil)
287
+ super(msg, code)
288
+ @result = result
289
+ end
290
+ attr_reader :result
291
+ end
292
+
293
+ class RemoteRuntimeError < RemoteRuntimeError
294
+ CODE = -10
295
+ def initialize(msg, result = nil)
296
+ super(msg, CODE, result)
297
+ end
298
+ end
299
+ =end
300
+
301
+
302
+ end
303
+ end
@@ -49,12 +49,14 @@ class Future
49
49
  return @result
50
50
  end
51
51
  end
52
+ if @result.nil?
53
+ # compatible error
54
+ raise RuntimeError.new(@error)
55
+ end
52
56
  if @error_handler
53
- return @error_handler.call(self)
54
- else
55
- raise @error if @error.is_a?(Error)
56
- raise RemoteError.new(@error, @result)
57
+ @error_handler.call(@error, @result)
57
58
  end
59
+ raise RPCError.create(@error, @result)
58
60
  end
59
61
 
60
62
  # Wait for receiving result of remote procedure call.
@@ -73,13 +75,6 @@ class Future
73
75
  # Attaches a callback method that is called when the result of remote method is received.
74
76
  def attach_callback(proc = nil, &block)
75
77
  @callback_handler = proc || block
76
- if @callback_handler.arity == 2
77
- # FIXME backward compatibility
78
- handler = @callback_handler
79
- @callback_handler = Proc.new {|future|
80
- handler.call(future.error, future.result)
81
- }
82
- end
83
78
  end
84
79
 
85
80
  # For IDL
@@ -95,10 +90,18 @@ class Future
95
90
  def set_result(err, res) #:nodoc:
96
91
  @error = err
97
92
  @result = res
93
+ @set = true
98
94
  if @callback_handler
99
- @callback_handler.call(self)
95
+ if @callback_handler.arity == 2
96
+ # FIXME backward compatibility
97
+ @callback_handler.call(error, result)
98
+ else
99
+ @callback_handler.call(self)
100
+ end
100
101
  end
101
- @set = true
102
+ self
103
+ rescue
104
+ self
102
105
  end
103
106
 
104
107
  def step_timeout #:nodoc:
@@ -0,0 +1,190 @@
1
+ #
2
+ # MessagePack-RPC for Ruby
3
+ #
4
+ # Copyright (C) 2010 FURUHASHI Sadayuki
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+ #
18
+ module MessagePack
19
+ module RPC
20
+
21
+
22
+ # MultiFuture bunldes up multiple Future objects.
23
+ class MultiFuture
24
+ def initialize
25
+ @all = []
26
+
27
+ @not_joined = []
28
+ @joined = []
29
+ @error = []
30
+ @success = []
31
+
32
+ @on_all = nil
33
+ @on_error = nil
34
+ @on_success = nil
35
+ @on_num = {} # {num => callback}
36
+ end
37
+
38
+ # Gets all registered Future objects.
39
+ attr_reader :all
40
+
41
+ # Gets Future objects which are not joined yet.
42
+ attr_reader :not_joined
43
+
44
+ # Gets Future objects which are already joined.
45
+ attr_reader :joined
46
+
47
+ # Gets Future objects which are joined as error.
48
+ attr_reader :error
49
+
50
+ # Gets Future objects which are joined as success.
51
+ attr_reader :success
52
+
53
+ # Clears all Future objects and all callback methods.
54
+ def clear
55
+ @all = []
56
+
57
+ @not_joined = []
58
+ @joined = []
59
+ @error = []
60
+ @success = []
61
+
62
+ clear_callback
63
+ end
64
+
65
+ # Clears all callback methods registered by on_xxx methods.
66
+ def clear_callback
67
+ @on_all = nil
68
+ @on_error = nil
69
+ @on_success = nil
70
+ @on_num = {}
71
+ self
72
+ end
73
+
74
+ # Registeres new Future object.
75
+ # Returns self.
76
+ def add(future)
77
+ future.attach_callback(&method(:callback))
78
+ @all << future
79
+ @not_joined << future
80
+ self
81
+ end
82
+
83
+ # Attaches a callback method that is called when
84
+ # all Future objects are joined.
85
+ # Returns self.
86
+ def on_all(&block)
87
+ @on_all = block
88
+ self
89
+ end
90
+
91
+ # Attaches a callback method that is called when
92
+ # Future objects are joined as success.
93
+ # Returns self.
94
+ def on_success(&block)
95
+ @on_success = block
96
+ self
97
+ end
98
+
99
+ # Attaches a callback method that is called when
100
+ # Future objects are joined as error.
101
+ # Returns self.
102
+ def on_error(&block)
103
+ @on_error = block
104
+ self
105
+ end
106
+
107
+ # Attaches a callback method that is called when
108
+ # specified number of Future objects are joined.
109
+ # Returns self.
110
+ def on_num(n, &block)
111
+ @on_num[n.to_i] = block
112
+ self
113
+ end
114
+
115
+ # Waits until all Future objects join.
116
+ def join_all
117
+ @not_joined.each {|future|
118
+ future.join
119
+ }
120
+ @all
121
+ end
122
+
123
+ # Waits until at least one Future object joins as success.
124
+ # Returns the joined Future object or nil.
125
+ def join_success
126
+ until @not_joined.empty?
127
+ unless @success.empty?
128
+ break
129
+ end
130
+ @not_joined.first.loop.run_once
131
+ end
132
+ @success.last
133
+ end
134
+
135
+ # Waits until at least one Future object joins as error.
136
+ # Returns the joined Future object or nil.
137
+ def join_error
138
+ until @not_joined.empty?
139
+ unless @error.empty?
140
+ break
141
+ end
142
+ @not_joined.first.loop.run_once
143
+ end
144
+ @error.last
145
+ end
146
+
147
+ # Waits until specified number of Future objects join.
148
+ # Returns the joined Future objects or nil.
149
+ def join_num(n)
150
+ until @not_joined.empty?
151
+ unless @joined.size >= n
152
+ return @joined
153
+ end
154
+ @not_joined.first.loop.run_once
155
+ end
156
+ nil
157
+ end
158
+
159
+ private
160
+
161
+ def callback(future)
162
+ if @not_joined.delete(future)
163
+ @joined << future
164
+
165
+ if future.error == nil
166
+ @success << future
167
+ if @on_success
168
+ @on_success.call(future) rescue nil
169
+ end
170
+ else
171
+ @error << future
172
+ if @on_error
173
+ @on_error.call(future) rescue nil
174
+ end
175
+ end
176
+
177
+ if callback = @on_num[@joined.size]
178
+ callback.call(@joined) rescue nil
179
+ end
180
+
181
+ if @on_all && @not_joined.empty?
182
+ @on_all.call(@all) rescue nil
183
+ end
184
+ end
185
+ end
186
+ end
187
+
188
+
189
+ end
190
+ end