msgpack-rpc 0.4.0 → 0.4.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.
@@ -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