qrpc 0.4.0 → 0.9.0
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/CHANGES.txt +9 -6
- data/Gemfile +10 -4
- data/Gemfile.lock +34 -12
- data/LICENSE.txt +1 -1
- data/README.md +92 -25
- data/Rakefile +2 -1
- data/TODO.md +1 -3
- data/VERSION +1 -1
- data/lib/qrpc/client.rb +13 -5
- data/lib/qrpc/client/dispatcher.rb +66 -50
- data/lib/qrpc/client/exception.rb +8 -37
- data/lib/qrpc/client/job.rb +49 -16
- data/lib/qrpc/general.rb +61 -1
- data/lib/qrpc/generator/object-id.rb +43 -0
- data/lib/qrpc/generator/uuid.rb +43 -0
- data/lib/qrpc/locator.rb +11 -85
- data/lib/qrpc/locator/em-jack.rb +160 -0
- data/lib/qrpc/locator/evented-queue.rb +101 -0
- data/lib/qrpc/protocol/abstract.rb +119 -0
- data/lib/qrpc/protocol/abstract/error.rb +54 -0
- data/lib/qrpc/protocol/abstract/object.rb +81 -0
- data/lib/qrpc/protocol/abstract/request.rb +126 -0
- data/lib/qrpc/protocol/abstract/response.rb +103 -0
- data/lib/qrpc/protocol/json-rpc.rb +32 -0
- data/lib/qrpc/protocol/json-rpc/error.rb +71 -0
- data/lib/qrpc/protocol/json-rpc/native/exception-data.rb +247 -0
- data/lib/qrpc/protocol/json-rpc/native/qrpc-object.rb +137 -0
- data/lib/qrpc/protocol/json-rpc/request.rb +140 -0
- data/lib/qrpc/protocol/json-rpc/response.rb +146 -0
- data/lib/qrpc/protocol/object.rb +32 -0
- data/lib/qrpc/protocol/object/error.rb +46 -0
- data/lib/qrpc/protocol/object/request.rb +111 -0
- data/lib/qrpc/protocol/object/response.rb +93 -0
- data/lib/qrpc/server.rb +63 -48
- data/lib/qrpc/server/dispatcher.rb +5 -107
- data/lib/qrpc/server/job.rb +69 -19
- data/qrpc.gemspec +55 -19
- data/test-both.rb +85 -0
- data/test-client.rb +36 -8
- data/test-server.rb +17 -12
- metadata +181 -31
- data/lib/qrpc/protocol/exception-data.rb +0 -227
- data/lib/qrpc/protocol/qrpc-object.rb +0 -103
- data/lib/qrpc/protocol/request.rb +0 -46
@@ -0,0 +1,126 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
require "abstract"
|
5
|
+
require "qrpc/general"
|
6
|
+
require "qrpc/protocol/abstract/object"
|
7
|
+
|
8
|
+
##
|
9
|
+
# General QRPC module.
|
10
|
+
#
|
11
|
+
|
12
|
+
module QRPC
|
13
|
+
|
14
|
+
##
|
15
|
+
# Protocols helper module.
|
16
|
+
# @since 0.9.0
|
17
|
+
#
|
18
|
+
|
19
|
+
module Protocol
|
20
|
+
|
21
|
+
##
|
22
|
+
# Abstract protocol implementation.
|
23
|
+
# @since 0.9.0
|
24
|
+
#
|
25
|
+
|
26
|
+
class Abstract
|
27
|
+
|
28
|
+
##
|
29
|
+
# Abstract request implementation.
|
30
|
+
#
|
31
|
+
# @since 0.9.0
|
32
|
+
# @abstract
|
33
|
+
#
|
34
|
+
|
35
|
+
class Request < Object
|
36
|
+
|
37
|
+
##
|
38
|
+
# Constructor.
|
39
|
+
#
|
40
|
+
# @param [Hash] init initial options
|
41
|
+
# @abstract
|
42
|
+
#
|
43
|
+
|
44
|
+
def initialize(init = { })
|
45
|
+
super(init)
|
46
|
+
if self.instance_of? Request
|
47
|
+
not_implemented
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Parses the data for new object.
|
53
|
+
#
|
54
|
+
# @param [String] raw raw data
|
55
|
+
# @return [Request] new request according to data
|
56
|
+
# @abstract
|
57
|
+
#
|
58
|
+
|
59
|
+
def self.parse(raw)
|
60
|
+
not_implemented
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Returns ID of the request.
|
65
|
+
#
|
66
|
+
# @return [Object] request ID
|
67
|
+
# @abstract
|
68
|
+
#
|
69
|
+
|
70
|
+
def id
|
71
|
+
not_implemented
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# Returns method identifier of the request.
|
76
|
+
#
|
77
|
+
# @return Symbol
|
78
|
+
# @abstract
|
79
|
+
#
|
80
|
+
|
81
|
+
def method
|
82
|
+
not_implemented
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Returns method params of the request.
|
87
|
+
#
|
88
|
+
# @return Array
|
89
|
+
# @abstract
|
90
|
+
#
|
91
|
+
|
92
|
+
def params
|
93
|
+
not_implemented
|
94
|
+
end
|
95
|
+
|
96
|
+
##
|
97
|
+
# Returns the QRPC request priority.
|
98
|
+
# @return Integer
|
99
|
+
#
|
100
|
+
|
101
|
+
def priority
|
102
|
+
not_implemented
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Returns the QRPC request client identifier.
|
107
|
+
# @return Object
|
108
|
+
#
|
109
|
+
|
110
|
+
def client
|
111
|
+
not_implemented
|
112
|
+
end
|
113
|
+
|
114
|
+
##
|
115
|
+
# Indicates, job is notification.
|
116
|
+
# @return Boolean
|
117
|
+
#
|
118
|
+
|
119
|
+
def notification?
|
120
|
+
not_implemented
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
require "abstract"
|
5
|
+
require "qrpc/general"
|
6
|
+
require "qrpc/protocol/abstract/object"
|
7
|
+
|
8
|
+
##
|
9
|
+
# General QRPC module.
|
10
|
+
#
|
11
|
+
|
12
|
+
module QRPC
|
13
|
+
|
14
|
+
##
|
15
|
+
# Protocols helper module.
|
16
|
+
# @since 0.9.0
|
17
|
+
#
|
18
|
+
|
19
|
+
module Protocol
|
20
|
+
|
21
|
+
##
|
22
|
+
# Abstract protocol implementation.
|
23
|
+
# @since 0.9.0
|
24
|
+
#
|
25
|
+
|
26
|
+
class Abstract
|
27
|
+
|
28
|
+
##
|
29
|
+
# Abstract response implementation.
|
30
|
+
#
|
31
|
+
# @since 0.9.0
|
32
|
+
# @abstract
|
33
|
+
#
|
34
|
+
|
35
|
+
class Response < Object
|
36
|
+
|
37
|
+
##
|
38
|
+
# Constructor.
|
39
|
+
#
|
40
|
+
# @param [Hash] init initial options
|
41
|
+
# @abstract
|
42
|
+
#
|
43
|
+
|
44
|
+
def initialize(init = { })
|
45
|
+
super(init)
|
46
|
+
if self.instance_of? Response
|
47
|
+
not_implemented
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
##
|
52
|
+
# Parses the data for new object.
|
53
|
+
#
|
54
|
+
# @param [String] raw raw data
|
55
|
+
# @return [Response] new response according to data
|
56
|
+
# @abstract
|
57
|
+
#
|
58
|
+
|
59
|
+
def self.parse(raw)
|
60
|
+
not_implemented
|
61
|
+
end
|
62
|
+
|
63
|
+
##
|
64
|
+
# Returns ID of the request.
|
65
|
+
# @return [Object] request ID
|
66
|
+
#
|
67
|
+
|
68
|
+
def id
|
69
|
+
not_implemented
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
##
|
74
|
+
# Returns response error.
|
75
|
+
# @return [Exception] error object
|
76
|
+
#
|
77
|
+
|
78
|
+
def error
|
79
|
+
not_implemented
|
80
|
+
end
|
81
|
+
|
82
|
+
##
|
83
|
+
# Indicates, error state of the response.
|
84
|
+
# @return [Boolean] error indication
|
85
|
+
#
|
86
|
+
|
87
|
+
def error?
|
88
|
+
not_implemented
|
89
|
+
end
|
90
|
+
|
91
|
+
##
|
92
|
+
# Returns response result.
|
93
|
+
# @return [Object] response result
|
94
|
+
#
|
95
|
+
|
96
|
+
def result
|
97
|
+
not_implemented
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
require "qrpc/protocol/abstract"
|
5
|
+
|
6
|
+
##
|
7
|
+
# General QRPC module.
|
8
|
+
#
|
9
|
+
|
10
|
+
module QRPC
|
11
|
+
|
12
|
+
##
|
13
|
+
# Protocols helper module.
|
14
|
+
# @since 0.9.0
|
15
|
+
#
|
16
|
+
|
17
|
+
module Protocol
|
18
|
+
|
19
|
+
##
|
20
|
+
# JSON-RPC protocol implementation.
|
21
|
+
# @since 0.9.0
|
22
|
+
#
|
23
|
+
|
24
|
+
class JsonRpc < Abstract
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
require "qrpc/protocol/json-rpc/error"
|
31
|
+
require "qrpc/protocol/json-rpc/request"
|
32
|
+
require "qrpc/protocol/json-rpc/response"
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
require "qrpc/general"
|
5
|
+
require "qrpc/protocol/abstract/error"
|
6
|
+
require "qrpc/protocol/json-rpc/native/exception-data"
|
7
|
+
|
8
|
+
##
|
9
|
+
# General QRPC module.
|
10
|
+
#
|
11
|
+
|
12
|
+
module QRPC
|
13
|
+
|
14
|
+
##
|
15
|
+
# Protocols helper module.
|
16
|
+
# @since 0.9.0
|
17
|
+
#
|
18
|
+
|
19
|
+
module Protocol
|
20
|
+
|
21
|
+
##
|
22
|
+
# JSON-RPC protocol implementation.
|
23
|
+
# @since 0.9.0
|
24
|
+
#
|
25
|
+
|
26
|
+
class JsonRpc
|
27
|
+
|
28
|
+
##
|
29
|
+
# JSON-RPC error implementation.
|
30
|
+
# @since 0.9.0
|
31
|
+
#
|
32
|
+
|
33
|
+
class Error < QRPC::Protocol::Abstract::Error
|
34
|
+
|
35
|
+
##
|
36
|
+
# Holds native object.
|
37
|
+
#
|
38
|
+
|
39
|
+
@native
|
40
|
+
|
41
|
+
##
|
42
|
+
# Returns the native object.
|
43
|
+
# @return [JsonRpcObjects::Generic::Error] native response object
|
44
|
+
#
|
45
|
+
|
46
|
+
def native
|
47
|
+
if @native.nil?
|
48
|
+
exception = @options.exception
|
49
|
+
request = @options.request
|
50
|
+
data = QRPC::Protocol::JsonRpc::Native::ExceptionData::create(exception)
|
51
|
+
|
52
|
+
@native = request.native.class::version.error::create(100, "exception raised during processing the request", :error => data.output)
|
53
|
+
@native.serializer = @options.serializer
|
54
|
+
end
|
55
|
+
|
56
|
+
@native
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Serializes object to the resultant form.
|
61
|
+
# @return [String] serialized form
|
62
|
+
#
|
63
|
+
|
64
|
+
def serialize
|
65
|
+
self.native.serialize
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,247 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# (c) 2011 Martin Kozák (martinkozak@martinkozak.net)
|
3
|
+
|
4
|
+
require "qrpc/protocol/json-rpc/native/qrpc-object"
|
5
|
+
require "json-rpc-objects/generic/object"
|
6
|
+
require "qrpc/protocol/json-rpc"
|
7
|
+
require "qrpc/general"
|
8
|
+
require "base64"
|
9
|
+
|
10
|
+
##
|
11
|
+
# General QRPC module.
|
12
|
+
#
|
13
|
+
|
14
|
+
module QRPC
|
15
|
+
|
16
|
+
##
|
17
|
+
# JSON RPC helper module.
|
18
|
+
# @since 0.2.0
|
19
|
+
#
|
20
|
+
|
21
|
+
module Protocol
|
22
|
+
|
23
|
+
##
|
24
|
+
# JSON-RPC protocol implementation.
|
25
|
+
# @since 0.9.0
|
26
|
+
#
|
27
|
+
|
28
|
+
class JsonRpc
|
29
|
+
|
30
|
+
##
|
31
|
+
# Native JSON-RPC classes.
|
32
|
+
# @since 0.9.0
|
33
|
+
#
|
34
|
+
|
35
|
+
module Native
|
36
|
+
|
37
|
+
##
|
38
|
+
# Exception data QRPC JSON-RPC object.
|
39
|
+
# @since 0.2.0
|
40
|
+
#
|
41
|
+
|
42
|
+
class ExceptionData < JsonRpcObjects::Generic::Object
|
43
|
+
|
44
|
+
##
|
45
|
+
# Holds JSON-RPC version indication.
|
46
|
+
#
|
47
|
+
|
48
|
+
VERSION = QRPC::Protocol::JsonRpc::Native::QrpcObject::VERSION
|
49
|
+
|
50
|
+
##
|
51
|
+
# Holds exception name.
|
52
|
+
# @return [Symbol]
|
53
|
+
#
|
54
|
+
|
55
|
+
attr_accessor :name
|
56
|
+
@name
|
57
|
+
|
58
|
+
##
|
59
|
+
# Holds exception message.
|
60
|
+
# @return [String]
|
61
|
+
#
|
62
|
+
|
63
|
+
attr_accessor :message
|
64
|
+
@message
|
65
|
+
|
66
|
+
##
|
67
|
+
# Holds backtrace. See readme for structure details.
|
68
|
+
# @return [Array]
|
69
|
+
#
|
70
|
+
|
71
|
+
attr_accessor :backtrace
|
72
|
+
@backtrace
|
73
|
+
|
74
|
+
##
|
75
|
+
# Holds native dump. See readme for structure details.
|
76
|
+
# @return [Class]
|
77
|
+
#
|
78
|
+
|
79
|
+
attr_accessor :dump
|
80
|
+
@dump
|
81
|
+
|
82
|
+
##
|
83
|
+
# Indicates, data are encoded and should be decoded.
|
84
|
+
#
|
85
|
+
|
86
|
+
@__encoded
|
87
|
+
|
88
|
+
##
|
89
|
+
# Creates new QRPC JSON-RPC object.
|
90
|
+
#
|
91
|
+
# @overload create(exception, nil, opts = { })
|
92
|
+
# Creates from exception.
|
93
|
+
# @param [Exception] exception exception object
|
94
|
+
# @param [NilClass] nil (not applicable)
|
95
|
+
# @param [Hash] opts optional members of object
|
96
|
+
# @overload create(name, message, opts = { })
|
97
|
+
# Creates from exception description.
|
98
|
+
# @param [Symbol, String] name exception name
|
99
|
+
# @param [Object] exception message
|
100
|
+
# @param [Hash] opts optional members of object
|
101
|
+
# @return [QRPC::Protocol::ExceptionData] new instance
|
102
|
+
#
|
103
|
+
|
104
|
+
def self.create(arg1, message = nil, opts = { })
|
105
|
+
if arg1.kind_of? ::Exception
|
106
|
+
mode = :decoded
|
107
|
+
data = {
|
108
|
+
:name => arg1.class.name,
|
109
|
+
:message => arg1.message,
|
110
|
+
:backtrace => arg1.backtrace,
|
111
|
+
:dump => {
|
112
|
+
"format" => "ruby",
|
113
|
+
"object" => arg1
|
114
|
+
}
|
115
|
+
}
|
116
|
+
else
|
117
|
+
mode = :encoded
|
118
|
+
data = {
|
119
|
+
:name => arg1,
|
120
|
+
:message => message
|
121
|
+
}
|
122
|
+
end
|
123
|
+
|
124
|
+
data.merge! opts
|
125
|
+
return self::new(data, mode)
|
126
|
+
end
|
127
|
+
|
128
|
+
##
|
129
|
+
# Constructor.
|
130
|
+
# @param [Hash] data for initializing the object
|
131
|
+
#
|
132
|
+
|
133
|
+
def initialize(data, mode = :encoded)
|
134
|
+
@__encoded = (mode == :encoded)
|
135
|
+
super(data)
|
136
|
+
end
|
137
|
+
|
138
|
+
##
|
139
|
+
# Checks correctness of the object data.
|
140
|
+
#
|
141
|
+
|
142
|
+
def check!
|
143
|
+
self.normalize!
|
144
|
+
|
145
|
+
if not @name.kind_of? Symbol
|
146
|
+
raise Exception::new("Exception name is expected to be Symbol or convertable to symbol.")
|
147
|
+
end
|
148
|
+
|
149
|
+
if not @backtrace.nil? and not @backtrace.kind_of? Array
|
150
|
+
raise Exception::new("Backtrace is expected to be an Array.")
|
151
|
+
end
|
152
|
+
|
153
|
+
if not @dump.nil?
|
154
|
+
if @dump.object.nil? and @dump.raw.nil?
|
155
|
+
raise Exception::new("Either object or RAW form of the dump must be set if dump is set.")
|
156
|
+
elsif @dump.format.nil? or not @dump.format.kind_of? Symbol
|
157
|
+
raise Exception::new("Dump format must be set and must be Symbol.")
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
##
|
163
|
+
# Renders data to output form.
|
164
|
+
# @return [Hash] with data of object
|
165
|
+
#
|
166
|
+
|
167
|
+
def output
|
168
|
+
result = {
|
169
|
+
"name" => @name.to_s,
|
170
|
+
"message" => @message,
|
171
|
+
}
|
172
|
+
|
173
|
+
# Backtrace
|
174
|
+
if @backtrace.kind_of? Array
|
175
|
+
result["backtrace"] = @backtrace.map { |i| Base64.encode64(i) }
|
176
|
+
end
|
177
|
+
|
178
|
+
# Dump
|
179
|
+
if not @dump.nil?
|
180
|
+
result["dump"] = {
|
181
|
+
"format" => @dump.format,
|
182
|
+
}
|
183
|
+
|
184
|
+
if not dump.object.nil?
|
185
|
+
raw = Base64.encode64(Marshal.dump(dump.object))
|
186
|
+
else
|
187
|
+
raw = dump.raw
|
188
|
+
end
|
189
|
+
|
190
|
+
result["dump"]["raw"] = raw
|
191
|
+
end
|
192
|
+
|
193
|
+
return result
|
194
|
+
end
|
195
|
+
|
196
|
+
|
197
|
+
protected
|
198
|
+
|
199
|
+
##
|
200
|
+
# Assigns data.
|
201
|
+
#
|
202
|
+
|
203
|
+
def data=(value, mode = nil)
|
204
|
+
data = __convert_data(value, mode)
|
205
|
+
|
206
|
+
# Required
|
207
|
+
@name = data[:name]
|
208
|
+
@message = data[:message]
|
209
|
+
|
210
|
+
# Backtrace
|
211
|
+
backtrace = data[:backtrace]
|
212
|
+
|
213
|
+
if @__encoded and (backtrace.kind_of? Array)
|
214
|
+
@backtrace = backtrace.map { |i| Base64.decode64(i) }
|
215
|
+
end
|
216
|
+
|
217
|
+
# Dump
|
218
|
+
dump = data[:dump]
|
219
|
+
|
220
|
+
if dump.kind_of? Hash
|
221
|
+
@dump = Struct::new(:format, :raw, :object)::new(dump["format"].downcase.to_sym, dump["raw"], dump["object"])
|
222
|
+
|
223
|
+
if not @dump.raw.nil? and @dump.object.nil? and (@dump.format == :ruby)
|
224
|
+
@dump.object = Marshal.load(Base64.decode64(@dump.raw))
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
end
|
229
|
+
|
230
|
+
##
|
231
|
+
# Converts data to standard (defined) format.
|
232
|
+
#
|
233
|
+
|
234
|
+
def normalize!
|
235
|
+
@name = @name.to_sym
|
236
|
+
|
237
|
+
if not @dump.nil?
|
238
|
+
@dump.format = @dump.format.to_sym
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|