qrpc 0.1.1 → 0.2.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 +11 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +8 -8
- data/README.md +31 -9
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/qrpc/client.rb +277 -0
- data/lib/qrpc/client/exception.rb +72 -0
- data/lib/qrpc/client/job.rb +150 -0
- data/lib/qrpc/general.rb +10 -0
- data/lib/qrpc/locator.rb +9 -6
- data/lib/qrpc/protocol/exception-data.rb +227 -0
- data/lib/qrpc/protocol/qrpc-object.rb +103 -0
- data/lib/qrpc/protocol/request.rb +46 -0
- data/lib/qrpc/server.rb +7 -10
- data/lib/qrpc/server/job.rb +9 -14
- data/qrpc.gemspec +17 -11
- data/test-client.rb +24 -0
- metadata +16 -38
@@ -0,0 +1,150 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "uuid"
|
3
|
+
require "qrpc/protocol/request"
|
4
|
+
require "qrpc/client/exception"
|
5
|
+
require "qrpc/general"
|
6
|
+
|
7
|
+
##
|
8
|
+
# General QRPC module.
|
9
|
+
#
|
10
|
+
|
11
|
+
module QRPC
|
12
|
+
|
13
|
+
##
|
14
|
+
# Queue RPC client.
|
15
|
+
#
|
16
|
+
|
17
|
+
class Client
|
18
|
+
|
19
|
+
##
|
20
|
+
# Queue RPC client job.
|
21
|
+
# @since 0.2.0
|
22
|
+
#
|
23
|
+
|
24
|
+
class Job
|
25
|
+
|
26
|
+
##
|
27
|
+
# Holds job ID.
|
28
|
+
#
|
29
|
+
|
30
|
+
@id
|
31
|
+
|
32
|
+
##
|
33
|
+
# Holds associated client ID.
|
34
|
+
#
|
35
|
+
|
36
|
+
@client_id
|
37
|
+
|
38
|
+
##
|
39
|
+
# Holds method name of the job.
|
40
|
+
#
|
41
|
+
|
42
|
+
@job
|
43
|
+
|
44
|
+
##
|
45
|
+
# Holds method arguments array.
|
46
|
+
#
|
47
|
+
|
48
|
+
@arguments
|
49
|
+
|
50
|
+
##
|
51
|
+
# Holds job callback.
|
52
|
+
#
|
53
|
+
|
54
|
+
@callback
|
55
|
+
|
56
|
+
##
|
57
|
+
# Message priority.
|
58
|
+
#
|
59
|
+
|
60
|
+
@priority
|
61
|
+
|
62
|
+
##
|
63
|
+
# Job result.
|
64
|
+
#
|
65
|
+
|
66
|
+
@result
|
67
|
+
|
68
|
+
##
|
69
|
+
# Constructor.
|
70
|
+
#
|
71
|
+
# @param [Symbol] client_id client (session) ID
|
72
|
+
# @param [Symbol] method job method name
|
73
|
+
# @param [Array] arguments array of arguments for job
|
74
|
+
# @param [Integer] priority job priority
|
75
|
+
# @param [Proc] callback result callback
|
76
|
+
#
|
77
|
+
|
78
|
+
def initialize(client_id, method, arguments = [ ], priority = QRPC::DEFAULT_PRIORITY, &callback)
|
79
|
+
@client_id = client_id
|
80
|
+
@method = method
|
81
|
+
@arguments = arguments
|
82
|
+
@callback = callback
|
83
|
+
@priority = priority
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# Returns job ID.
|
88
|
+
# @return [Symbol] job ID
|
89
|
+
#
|
90
|
+
|
91
|
+
def id
|
92
|
+
if @id.nil?
|
93
|
+
@id = UUID.generate.to_sym
|
94
|
+
end
|
95
|
+
|
96
|
+
return @id
|
97
|
+
end
|
98
|
+
|
99
|
+
##
|
100
|
+
# Converts job to JSON.
|
101
|
+
# @return [String] job in JSON form (JSON-RPC)
|
102
|
+
#
|
103
|
+
|
104
|
+
def to_json
|
105
|
+
QRPC::Protocol::Request::create(@client_id, @id, @method, @arguments, @priority).to_json
|
106
|
+
end
|
107
|
+
|
108
|
+
##
|
109
|
+
# Indicates message is notification. So callback isn't set
|
110
|
+
# and it doesn't expect any result.
|
111
|
+
#
|
112
|
+
# @return [Boolean] +true+ if it's, +false+ in otherwise
|
113
|
+
#
|
114
|
+
|
115
|
+
def notification?
|
116
|
+
@callback.nil?
|
117
|
+
end
|
118
|
+
|
119
|
+
##
|
120
|
+
# Assigns job result and subsequently calls callback.
|
121
|
+
# @param [JsonRpcObjects::Generic::Response] result of the call
|
122
|
+
#
|
123
|
+
|
124
|
+
def assign_result(result)
|
125
|
+
if not result.error?
|
126
|
+
@result = result.result
|
127
|
+
else
|
128
|
+
=begin
|
129
|
+
STDERR.write(">>> Exception while call ID: " << self.id.to_s << "\n")
|
130
|
+
=end
|
131
|
+
exception = QRPC::Client::Exception::get(result.error)
|
132
|
+
=begin
|
133
|
+
STDERR.write exception.class.name.dup << ": " << exception.message << "\n"
|
134
|
+
|
135
|
+
exception.backtrace.each do |i|
|
136
|
+
STDERR.write " from " << i << "\n"
|
137
|
+
end
|
138
|
+
=end
|
139
|
+
raise exception
|
140
|
+
end
|
141
|
+
|
142
|
+
if not @callback.nil?
|
143
|
+
@callback.call(@result)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|
149
|
+
end
|
150
|
+
end
|
data/lib/qrpc/general.rb
CHANGED
@@ -8,20 +8,30 @@ module QRPC
|
|
8
8
|
|
9
9
|
##
|
10
10
|
# Prefix for handled queues.
|
11
|
+
# @since 0.1.1
|
11
12
|
#
|
12
13
|
|
13
14
|
QUEUE_PREFIX = "qrpc"
|
14
15
|
|
15
16
|
##
|
16
17
|
# Input queue postfix.
|
18
|
+
# @since 0.1.1
|
17
19
|
#
|
18
20
|
|
19
21
|
QUEUE_POSTFIX_INPUT = "input"
|
20
22
|
|
21
23
|
##
|
22
24
|
# Output queue postfix.
|
25
|
+
# @since 0.1.1
|
23
26
|
#
|
24
27
|
|
25
28
|
QUEUE_POSTFIX_OUTPUT = "output"
|
29
|
+
|
30
|
+
##
|
31
|
+
# Indicates default job priority.
|
32
|
+
# @since 0.2.0
|
33
|
+
#
|
34
|
+
|
35
|
+
DEFAULT_PRIORITY = 50
|
26
36
|
|
27
37
|
end
|
data/lib/qrpc/locator.rb
CHANGED
@@ -15,24 +15,27 @@ module QRPC
|
|
15
15
|
|
16
16
|
##
|
17
17
|
# Contains queue name.
|
18
|
+
# @return [Symbol]
|
18
19
|
#
|
19
|
-
|
20
|
-
@queue
|
20
|
+
|
21
21
|
attr_accessor :queue
|
22
|
+
@queue
|
22
23
|
|
23
24
|
##
|
24
25
|
# Contains host.
|
26
|
+
# @return [String]
|
25
27
|
#
|
26
|
-
|
27
|
-
@host
|
28
|
+
|
28
29
|
attr_accessor :host
|
30
|
+
@host
|
29
31
|
|
30
32
|
##
|
31
33
|
# Contains port.
|
34
|
+
# @return [Integer]
|
32
35
|
#
|
33
|
-
|
34
|
-
@port
|
36
|
+
|
35
37
|
attr_accessor :port
|
38
|
+
@port
|
36
39
|
|
37
40
|
##
|
38
41
|
# Parser.
|
@@ -0,0 +1,227 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "json-rpc-objects/generic/object"
|
3
|
+
require "qrpc/protocol/qrpc-object"
|
4
|
+
require "base64"
|
5
|
+
|
6
|
+
##
|
7
|
+
# General QRPC module.
|
8
|
+
#
|
9
|
+
|
10
|
+
module QRPC
|
11
|
+
|
12
|
+
##
|
13
|
+
# JSON RPC helper module.
|
14
|
+
# @since 0.2.0
|
15
|
+
#
|
16
|
+
|
17
|
+
module Protocol
|
18
|
+
|
19
|
+
##
|
20
|
+
# Exception data QRPC JSON-RPC object.
|
21
|
+
# @since 0.2.0
|
22
|
+
#
|
23
|
+
|
24
|
+
class ExceptionData < JsonRpcObjects::Generic::Object
|
25
|
+
|
26
|
+
##
|
27
|
+
# Holds JSON-RPC version indication.
|
28
|
+
#
|
29
|
+
|
30
|
+
VERSION = QRPC::Protocol::QrpcObject::VERSION
|
31
|
+
|
32
|
+
##
|
33
|
+
# Holds exception name.
|
34
|
+
# @return [Symbol]
|
35
|
+
#
|
36
|
+
|
37
|
+
attr_accessor :name
|
38
|
+
@name
|
39
|
+
|
40
|
+
##
|
41
|
+
# Holds exception message.
|
42
|
+
# @return [String]
|
43
|
+
#
|
44
|
+
|
45
|
+
attr_accessor :message
|
46
|
+
@message
|
47
|
+
|
48
|
+
##
|
49
|
+
# Holds backtrace. See readme for structure details.
|
50
|
+
# @return [Array]
|
51
|
+
#
|
52
|
+
|
53
|
+
attr_accessor :backtrace
|
54
|
+
@backtrace
|
55
|
+
|
56
|
+
##
|
57
|
+
# Holds native dump. See readme for structure details.
|
58
|
+
# @return [Class]
|
59
|
+
#
|
60
|
+
|
61
|
+
attr_accessor :dump
|
62
|
+
@dump
|
63
|
+
|
64
|
+
##
|
65
|
+
# Indicates, data are encoded and should be decoded.
|
66
|
+
#
|
67
|
+
|
68
|
+
@__encoded
|
69
|
+
|
70
|
+
##
|
71
|
+
# Creates new QRPC JSON-RPC object.
|
72
|
+
#
|
73
|
+
# @overload create(exception, nil, opts = { })
|
74
|
+
# Creates from exception.
|
75
|
+
# @param [Exception] exception exception object
|
76
|
+
# @param [NilClass] nil (not applicable)
|
77
|
+
# @param [Hash] opts optional members of object
|
78
|
+
# @overload create(name, message, opts = { })
|
79
|
+
# Creates from exception description.
|
80
|
+
# @param [Symbol, String] name exception name
|
81
|
+
# @param [Object] exception message
|
82
|
+
# @param [Hash] opts optional members of object
|
83
|
+
# @return [QRPC::Protocol::ExceptionData] new instance
|
84
|
+
#
|
85
|
+
|
86
|
+
def self.create(arg1, message = nil, opts = { })
|
87
|
+
if arg1.kind_of? ::Exception
|
88
|
+
mode = :decoded
|
89
|
+
data = {
|
90
|
+
:name => arg1.class.name,
|
91
|
+
:message => arg1.message,
|
92
|
+
:backtrace => arg1.backtrace,
|
93
|
+
:dump => {
|
94
|
+
"format" => "ruby",
|
95
|
+
"object" => arg1
|
96
|
+
}
|
97
|
+
}
|
98
|
+
else
|
99
|
+
mode = :encoded
|
100
|
+
data = {
|
101
|
+
:name => arg1,
|
102
|
+
:message => message
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
data.merge! opts
|
107
|
+
return self::new(data, mode)
|
108
|
+
end
|
109
|
+
|
110
|
+
##
|
111
|
+
# Constructor.
|
112
|
+
# @param [Hash] data for initializing the object
|
113
|
+
#
|
114
|
+
|
115
|
+
def initialize(data, mode = :encoded)
|
116
|
+
@__encoded = (mode == :encoded)
|
117
|
+
super(data)
|
118
|
+
end
|
119
|
+
|
120
|
+
##
|
121
|
+
# Checks correctness of the object data.
|
122
|
+
#
|
123
|
+
|
124
|
+
def check!
|
125
|
+
self.normalize!
|
126
|
+
|
127
|
+
if not @name.kind_of? Symbol
|
128
|
+
raise Exception::new("Exception name is expected to be Symbol or convertable to symbol.")
|
129
|
+
end
|
130
|
+
|
131
|
+
if not @backtrace.nil? and not @backtrace.kind_of? Array
|
132
|
+
raise Exception::new("Backtrace is expected to be an Array.")
|
133
|
+
end
|
134
|
+
|
135
|
+
if not @dump.nil?
|
136
|
+
if @dump.object.nil? and @dump.raw.nil?
|
137
|
+
raise Exception::new("Either object or RAW form of the dump must be set if dump is set.")
|
138
|
+
elsif @dump.format.nil? or not @dump.format.kind_of? Symbol
|
139
|
+
raise Exception::new("Dump format must be set and must be Symbol.")
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
##
|
145
|
+
# Renders data to output form.
|
146
|
+
# @return [Hash] with data of object
|
147
|
+
#
|
148
|
+
|
149
|
+
def output
|
150
|
+
result = {
|
151
|
+
:name => @name.to_s,
|
152
|
+
:message => @message,
|
153
|
+
}
|
154
|
+
|
155
|
+
# Backtrace
|
156
|
+
if @backtrace.kind_of? Array
|
157
|
+
result[:backtrace] = @backtrace.map { |i| Base64.encode64(i) }
|
158
|
+
end
|
159
|
+
|
160
|
+
# Dump
|
161
|
+
if not @dump.nil?
|
162
|
+
result[:dump] = {
|
163
|
+
:format => @dump.format,
|
164
|
+
}
|
165
|
+
|
166
|
+
if not dump.object.nil?
|
167
|
+
raw = Base64.encode64(Marshal.dump(dump.object))
|
168
|
+
else
|
169
|
+
raw = dump.raw
|
170
|
+
end
|
171
|
+
|
172
|
+
result[:dump][:raw] = raw
|
173
|
+
end
|
174
|
+
|
175
|
+
return result
|
176
|
+
end
|
177
|
+
|
178
|
+
|
179
|
+
protected
|
180
|
+
|
181
|
+
##
|
182
|
+
# Assigns data.
|
183
|
+
#
|
184
|
+
|
185
|
+
def data=(value, mode = nil)
|
186
|
+
data = __convert_data(value, mode)
|
187
|
+
|
188
|
+
# Required
|
189
|
+
@name = data[:name]
|
190
|
+
@message = data[:message]
|
191
|
+
|
192
|
+
# Backtrace
|
193
|
+
backtrace = data[:backtrace]
|
194
|
+
|
195
|
+
if @__encoded and (backtrace.kind_of? Array)
|
196
|
+
@backtrace = backtrace.map { |i| Base64.decode64(i) }
|
197
|
+
end
|
198
|
+
|
199
|
+
# Dump
|
200
|
+
dump = data[:dump]
|
201
|
+
|
202
|
+
if dump.kind_of? Hash
|
203
|
+
@dump = Struct::new(:format, :raw, :object)::new(dump["format"].downcase.to_sym, dump["raw"], dump["object"])
|
204
|
+
|
205
|
+
if not @dump.raw.nil? and @dump.object.nil? and (@dump.format == :ruby)
|
206
|
+
@dump.object = Marshal.load(Base64.decode64(@dump.raw))
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
end
|
211
|
+
|
212
|
+
##
|
213
|
+
# Converts data to standard (defined) format.
|
214
|
+
#
|
215
|
+
|
216
|
+
def normalize!
|
217
|
+
@name = @name.to_sym
|
218
|
+
|
219
|
+
if not @dump.nil?
|
220
|
+
@dump.format = @dump.format.to_sym
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
|
226
|
+
end
|
227
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require "json-rpc-objects/generic/object"
|
3
|
+
require "json-rpc-objects/request"
|
4
|
+
|
5
|
+
##
|
6
|
+
# General QRPC module.
|
7
|
+
#
|
8
|
+
|
9
|
+
module QRPC
|
10
|
+
|
11
|
+
##
|
12
|
+
# JSON RPC helper module.
|
13
|
+
# @since 0.2.0
|
14
|
+
#
|
15
|
+
|
16
|
+
module Protocol
|
17
|
+
|
18
|
+
##
|
19
|
+
# QRPC JSON-RPC QRPC object. Extends the
|
20
|
+
# +JsonRpcObjects::Generic::Object+. See its documentation for
|
21
|
+
# additional methods.
|
22
|
+
#
|
23
|
+
# @since 0.2.0
|
24
|
+
#
|
25
|
+
|
26
|
+
class QrpcObject < JsonRpcObjects::Generic::Object
|
27
|
+
|
28
|
+
##
|
29
|
+
# Holds JSON-RPC version indication.
|
30
|
+
#
|
31
|
+
|
32
|
+
VERSION = JsonRpcObjects::Request::VERSION
|
33
|
+
|
34
|
+
##
|
35
|
+
# Creates new QRPC JSON-RPC object.
|
36
|
+
#
|
37
|
+
# @param [Hash] QRPC object optional arguments
|
38
|
+
# @return [QRPC::Protocol::QrpcObject] new instance
|
39
|
+
#
|
40
|
+
|
41
|
+
def self.create(opts = { })
|
42
|
+
self::new(opts)
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Checks correctness of the object data.
|
47
|
+
#
|
48
|
+
|
49
|
+
def check!
|
50
|
+
self.normalize!
|
51
|
+
|
52
|
+
if (not @priority.nil?) and not (@priority.kind_of? Numeric)
|
53
|
+
raise Exception::new("Priority is expected to be Numeric.")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Renders data to output form.
|
59
|
+
# @return [Hash] with data of object
|
60
|
+
#
|
61
|
+
|
62
|
+
def output
|
63
|
+
result = { :version => :"1.0.1" }
|
64
|
+
|
65
|
+
if not @priority.nil?
|
66
|
+
result[:priority] = @priority
|
67
|
+
end
|
68
|
+
|
69
|
+
if not @client.nil?
|
70
|
+
result[:client] = @client
|
71
|
+
end
|
72
|
+
|
73
|
+
return result
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
protected
|
78
|
+
|
79
|
+
##
|
80
|
+
# Assigns data.
|
81
|
+
#
|
82
|
+
|
83
|
+
def data=(value, mode = nil)
|
84
|
+
data = __convert_data(value, mode)
|
85
|
+
|
86
|
+
@priority = data[:priority]
|
87
|
+
@client = data[:client]
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Converts data to standard (defined) format.
|
92
|
+
#
|
93
|
+
|
94
|
+
def normalize!
|
95
|
+
if not @priority.nil?
|
96
|
+
@priority = @priority.to_i
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|