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.
- data/ChangeLog +17 -0
- data/lib/msgpack/rpc.rb +98 -13
- data/lib/msgpack/rpc/client.rb +2 -2
- data/lib/msgpack/rpc/dispatcher.rb +9 -71
- data/lib/msgpack/rpc/exception.rb +169 -11
- data/lib/msgpack/rpc/exception.rb.old +303 -0
- data/lib/msgpack/rpc/future.rb +16 -13
- data/lib/msgpack/rpc/multi_future.rb +190 -0
- data/lib/msgpack/rpc/server.rb +106 -5
- data/lib/msgpack/rpc/session.rb +51 -11
- data/lib/msgpack/rpc/transport/tcp.rb +12 -3
- data/lib/msgpack/rpc/transport/udp.rb +9 -3
- data/lib/msgpack/rpc/transport/unix.rb +12 -3
- data/lib/msgpack/rpc/version.rb +7 -0
- data/test/msgpack_rpc_test.rb +0 -1
- data/test/test_helper.rb +4 -0
- metadata +48 -21
@@ -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
|
data/lib/msgpack/rpc/future.rb
CHANGED
@@ -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
|
-
|
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.
|
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
|
-
|
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
|