protobuf 2.8.13 → 3.0.0.rc1
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.
- checksums.yaml +4 -4
- data/CHANGES.md +84 -5
- data/CONTRIBUTING.md +3 -3
- data/Rakefile +46 -7
- data/lib/protobuf/cli.rb +2 -20
- data/lib/protobuf/decoder.rb +74 -0
- data/lib/protobuf/deprecator.rb +42 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +17 -16
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +86 -85
- data/lib/protobuf/encoder.rb +62 -0
- data/lib/protobuf/enum.rb +298 -37
- data/lib/protobuf/field/base_field.rb +41 -27
- data/lib/protobuf/field/bool_field.rb +22 -4
- data/lib/protobuf/field/bytes_field.rb +36 -15
- data/lib/protobuf/field/double_field.rb +10 -3
- data/lib/protobuf/field/enum_field.rb +21 -18
- data/lib/protobuf/field/field_array.rb +26 -16
- data/lib/protobuf/field/fixed32_field.rb +10 -4
- data/lib/protobuf/field/fixed64_field.rb +10 -3
- data/lib/protobuf/field/float_field.rb +18 -5
- data/lib/protobuf/field/int32_field.rb +14 -4
- data/lib/protobuf/field/int64_field.rb +14 -4
- data/lib/protobuf/field/integer_field.rb +9 -4
- data/lib/protobuf/field/message_field.rb +16 -7
- data/lib/protobuf/field/sfixed32_field.rb +10 -3
- data/lib/protobuf/field/sfixed64_field.rb +12 -7
- data/lib/protobuf/field/signed_integer_field.rb +7 -0
- data/lib/protobuf/field/sint32_field.rb +14 -4
- data/lib/protobuf/field/sint64_field.rb +14 -4
- data/lib/protobuf/field/string_field.rb +11 -1
- data/lib/protobuf/field/uint32_field.rb +14 -4
- data/lib/protobuf/field/uint64_field.rb +14 -4
- data/lib/protobuf/field/varint_field.rb +11 -9
- data/lib/protobuf/field.rb +42 -25
- data/lib/protobuf/generators/enum_generator.rb +12 -1
- data/lib/protobuf/generators/field_generator.rb +1 -1
- data/lib/protobuf/lifecycle.rb +3 -4
- data/lib/protobuf/message/fields.rb +122 -0
- data/lib/protobuf/message/serialization.rb +84 -0
- data/lib/protobuf/message.rb +21 -221
- data/lib/protobuf/optionable.rb +23 -0
- data/lib/protobuf/rpc/client.rb +2 -4
- data/lib/protobuf/rpc/connector.rb +0 -2
- data/lib/protobuf/rpc/connectors/common.rb +2 -2
- data/lib/protobuf/rpc/dynamic_discovery.pb.rb +14 -16
- data/lib/protobuf/rpc/env.rb +58 -0
- data/lib/protobuf/rpc/error.rb +8 -5
- data/lib/protobuf/rpc/middleware/exception_handler.rb +36 -0
- data/lib/protobuf/rpc/middleware/logger.rb +91 -0
- data/lib/protobuf/rpc/middleware/request_decoder.rb +83 -0
- data/lib/protobuf/rpc/middleware/response_encoder.rb +88 -0
- data/lib/protobuf/rpc/middleware/runner.rb +18 -0
- data/lib/protobuf/rpc/middleware.rb +25 -0
- data/lib/protobuf/rpc/rpc.pb.rb +15 -16
- data/lib/protobuf/rpc/server.rb +14 -64
- data/lib/protobuf/rpc/servers/socket/server.rb +0 -2
- data/lib/protobuf/rpc/servers/socket/worker.rb +11 -15
- data/lib/protobuf/rpc/servers/zmq/util.rb +4 -1
- data/lib/protobuf/rpc/servers/zmq/worker.rb +5 -13
- data/lib/protobuf/rpc/servers/zmq_runner.rb +1 -1
- data/lib/protobuf/rpc/service.rb +38 -72
- data/lib/protobuf/rpc/service_dispatcher.rb +20 -108
- data/lib/protobuf/version.rb +1 -2
- data/lib/protobuf.rb +5 -13
- data/protobuf.gemspec +5 -5
- data/spec/benchmark/tasks.rb +2 -77
- data/spec/functional/zmq_server_spec.rb +13 -21
- data/spec/lib/protobuf/cli_spec.rb +5 -43
- data/spec/lib/protobuf/enum_spec.rb +194 -61
- data/spec/lib/protobuf/field_spec.rb +194 -0
- data/spec/lib/protobuf/generators/enum_generator_spec.rb +24 -1
- data/spec/lib/protobuf/generators/field_generator_spec.rb +6 -6
- data/spec/lib/protobuf/message_spec.rb +52 -70
- data/spec/lib/protobuf/optionable_spec.rb +46 -0
- data/spec/lib/protobuf/rpc/client_spec.rb +1 -93
- data/spec/lib/protobuf/rpc/connector_spec.rb +1 -7
- data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +8 -0
- data/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +62 -0
- data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +49 -0
- data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +115 -0
- data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +75 -0
- data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +0 -6
- data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +10 -0
- data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +30 -105
- data/spec/lib/protobuf/rpc/service_filters_spec.rb +4 -4
- data/spec/lib/protobuf/rpc/service_spec.rb +20 -24
- data/spec/lib/protobuf_spec.rb +3 -3
- data/spec/spec_helper.rb +5 -4
- data/spec/support/packed_field.rb +15 -14
- data/spec/support/server.rb +4 -21
- data/spec/support/test/defaults.pb.rb +4 -4
- data/spec/support/test/enum.pb.rb +13 -1
- data/spec/support/test/enum.proto +15 -0
- data/spec/support/test/extended.pb.rb +1 -1
- data/spec/support/test/google_unittest.pb.rb +239 -241
- data/spec/support/test/google_unittest_import.pb.rb +2 -2
- data/spec/support/test/multi_field_extensions.pb.rb +2 -2
- data/spec/support/test/resource.pb.rb +19 -18
- data/spec/support/test/resource.proto +1 -0
- data/spec/support/test/resource_service.rb +5 -0
- metadata +78 -57
- data/bin/rprotoc +0 -8
- data/lib/protobuf/enum_value.rb +0 -85
- data/lib/protobuf/evented.rb +0 -37
- data/lib/protobuf/ext/eventmachine.rb +0 -14
- data/lib/protobuf/field/extension_fields.rb +0 -32
- data/lib/protobuf/message/decoder.rb +0 -72
- data/lib/protobuf/message/message.rb +0 -1
- data/lib/protobuf/rpc/connectors/em_client.rb +0 -84
- data/lib/protobuf/rpc/connectors/eventmachine.rb +0 -87
- data/lib/protobuf/rpc/servers/evented/server.rb +0 -36
- data/lib/protobuf/rpc/servers/evented_runner.rb +0 -31
- data/spec/functional/embedded_service_spec.rb +0 -7
- data/spec/functional/evented_server_spec.rb +0 -64
- data/spec/lib/protobuf/enum_value_spec.rb +0 -29
- data/spec/lib/protobuf/rpc/servers/evented_server_spec.rb +0 -19
data/lib/protobuf/rpc/client.rb
CHANGED
@@ -134,7 +134,7 @@ module Protobuf
|
|
134
134
|
end
|
135
135
|
end
|
136
136
|
|
137
|
-
# Send the request to the service
|
137
|
+
# Send the request to the service.
|
138
138
|
# This method is usually never called directly
|
139
139
|
# but is invoked by method_missing (see docs above).
|
140
140
|
#
|
@@ -163,8 +163,6 @@ module Protobuf
|
|
163
163
|
|
164
164
|
end
|
165
165
|
|
166
|
-
|
167
|
-
ActiveSupport.run_load_hooks(:protobuf_rpc_client, Client)
|
168
|
-
end
|
166
|
+
ActiveSupport.run_load_hooks(:protobuf_rpc_client, Client)
|
169
167
|
end
|
170
168
|
end
|
@@ -7,8 +7,6 @@ module Protobuf
|
|
7
7
|
# Returns a connector class for the pre-defined connector_type.
|
8
8
|
def self.connector_for_client
|
9
9
|
case ::Protobuf.connector_type
|
10
|
-
when :evented then
|
11
|
-
::Protobuf::Rpc::Connectors::EventMachine
|
12
10
|
when :zmq then
|
13
11
|
::Protobuf::Rpc::Connectors::Zmq
|
14
12
|
else
|
@@ -40,7 +40,7 @@ module Protobuf
|
|
40
40
|
# @param [String] message The error message
|
41
41
|
def fail(code, message)
|
42
42
|
@error = ClientError.new
|
43
|
-
@error.code =
|
43
|
+
@error.code = Protobuf::Socketrpc::ErrorReason.fetch(code)
|
44
44
|
@error.message = message
|
45
45
|
log_debug { sign_message("Server failed request (invoking on_failure): #{@error.inspect}") }
|
46
46
|
|
@@ -74,7 +74,7 @@ module Protobuf
|
|
74
74
|
log_debug { sign_message("Parsing response from server (connection closed)") }
|
75
75
|
|
76
76
|
# Parse out the raw response
|
77
|
-
@stats.response_size = @response_data.size
|
77
|
+
@stats.response_size = @response_data.size unless @response_data.nil?
|
78
78
|
response_wrapper = Protobuf::Socketrpc::Response.decode(@response_data)
|
79
79
|
|
80
80
|
# Determine success or failure based on parsed data
|
@@ -4,11 +4,9 @@
|
|
4
4
|
require 'protobuf/message'
|
5
5
|
|
6
6
|
module Protobuf
|
7
|
-
|
8
7
|
module Rpc
|
9
|
-
|
10
8
|
module DynamicDiscovery
|
11
|
-
|
9
|
+
|
12
10
|
##
|
13
11
|
# Enum Classes
|
14
12
|
#
|
@@ -16,34 +14,34 @@ module Protobuf
|
|
16
14
|
define :HEARTBEAT, 0
|
17
15
|
define :FLATLINE, 1
|
18
16
|
end
|
19
|
-
|
20
|
-
|
17
|
+
|
18
|
+
|
21
19
|
##
|
22
20
|
# Message Classes
|
23
21
|
#
|
24
22
|
class Server < ::Protobuf::Message; end
|
25
23
|
class Beacon < ::Protobuf::Message; end
|
26
|
-
|
24
|
+
|
25
|
+
|
27
26
|
##
|
28
27
|
# Message Fields
|
29
28
|
#
|
30
29
|
class Server
|
31
|
-
optional
|
32
|
-
optional
|
33
|
-
optional
|
34
|
-
optional
|
35
|
-
repeated
|
30
|
+
optional :string, :uuid, 1
|
31
|
+
optional :string, :address, 2
|
32
|
+
optional :string, :port, 3
|
33
|
+
optional :int32, :ttl, 4
|
34
|
+
repeated :string, :services, 5
|
36
35
|
end
|
37
|
-
|
36
|
+
|
38
37
|
class Beacon
|
39
38
|
optional ::Protobuf::Rpc::DynamicDiscovery::BeaconType, :beacon_type, 1
|
40
39
|
optional ::Protobuf::Rpc::DynamicDiscovery::Server, :server, 2
|
41
40
|
end
|
42
|
-
|
43
|
-
|
41
|
+
|
44
42
|
end
|
45
|
-
|
43
|
+
|
46
44
|
end
|
47
|
-
|
45
|
+
|
48
46
|
end
|
49
47
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
class Env < Hash
|
4
|
+
# Creates an accessor that simply sets and reads a key in the hash:
|
5
|
+
#
|
6
|
+
# class Config < Hash
|
7
|
+
# hash_accessor :app
|
8
|
+
# end
|
9
|
+
#
|
10
|
+
# config = Config.new
|
11
|
+
# config.app = Foo
|
12
|
+
# config[:app] #=> Foo
|
13
|
+
#
|
14
|
+
# config[:app] = Bar
|
15
|
+
# config.app #=> Bar
|
16
|
+
#
|
17
|
+
def self.hash_accessor(*names) #:nodoc:
|
18
|
+
names.each do |name|
|
19
|
+
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
20
|
+
def #{name}
|
21
|
+
self['#{name}']
|
22
|
+
end
|
23
|
+
|
24
|
+
def #{name}=(value)
|
25
|
+
self['#{name}'] = value
|
26
|
+
end
|
27
|
+
|
28
|
+
def #{name}?
|
29
|
+
! self['#{name}'].nil?
|
30
|
+
end
|
31
|
+
METHOD
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# TODO: Add extra info about the environment (i.e. variables) and other
|
36
|
+
# information that might be useful
|
37
|
+
hash_accessor :client_host,
|
38
|
+
:encoded_request,
|
39
|
+
:encoded_response,
|
40
|
+
:log_signature,
|
41
|
+
:method_name,
|
42
|
+
:request,
|
43
|
+
:request_type,
|
44
|
+
:response,
|
45
|
+
:response_type,
|
46
|
+
:rpc_method,
|
47
|
+
:rpc_service,
|
48
|
+
:service_name,
|
49
|
+
:worker_id
|
50
|
+
|
51
|
+
def initialize(options={})
|
52
|
+
merge!(options)
|
53
|
+
|
54
|
+
self['worker_id'] = ::Thread.current.object_id.to_s(16)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
data/lib/protobuf/rpc/error.rb
CHANGED
@@ -8,14 +8,17 @@ module Protobuf
|
|
8
8
|
class PbError < StandardError
|
9
9
|
attr_reader :error_type
|
10
10
|
|
11
|
-
def initialize
|
12
|
-
@error_type = error_type.is_a?(String) ?
|
11
|
+
def initialize(message='An unknown RpcError occurred', error_type='RPC_ERROR')
|
12
|
+
@error_type = error_type.is_a?(String) ? Socketrpc::ErrorReason.const_get(error_type) : error_type
|
13
13
|
super message
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
17
|
-
|
18
|
-
|
16
|
+
def encode
|
17
|
+
to_response.encode
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_response
|
21
|
+
Socketrpc::Response.new(:error => message, :error_reason => error_type)
|
19
22
|
end
|
20
23
|
end
|
21
24
|
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
module Middleware
|
4
|
+
class ExceptionHandler
|
5
|
+
include ::Protobuf::Logger::LogMethods
|
6
|
+
|
7
|
+
attr_reader :app
|
8
|
+
|
9
|
+
def initialize(app)
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
app.call(env)
|
15
|
+
rescue => exception
|
16
|
+
log_exception(exception)
|
17
|
+
|
18
|
+
# Rescue exceptions, re-wrap them as generic Protobuf errors,
|
19
|
+
# and encode them
|
20
|
+
env.response = wrap_exception(exception)
|
21
|
+
env.encoded_response = env.response.encode
|
22
|
+
env
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Wrap exceptions in a generic Protobuf errors unless they already are
|
28
|
+
#
|
29
|
+
def wrap_exception(exception)
|
30
|
+
exception = RpcFailed.new(exception.message) unless exception.is_a?(PbError)
|
31
|
+
exception
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
module Middleware
|
4
|
+
class Logger
|
5
|
+
def initialize(app)
|
6
|
+
@app = app
|
7
|
+
end
|
8
|
+
|
9
|
+
# TODO: Figure out how to control when logs are flushed
|
10
|
+
def call(env)
|
11
|
+
instrumenter.start
|
12
|
+
instrumenter.flush(env) # Log request stats
|
13
|
+
|
14
|
+
env = @app.call(env)
|
15
|
+
|
16
|
+
instrumenter.stop
|
17
|
+
instrumenter.flush(env) # Log response stats
|
18
|
+
|
19
|
+
env
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def instrumenter
|
25
|
+
@instrumenter ||= Instrumenter.new
|
26
|
+
end
|
27
|
+
|
28
|
+
# TODO: Replace this with ActiveSupport::Notifications and log subscribers
|
29
|
+
# TODO: Consider adopting Rails-style logging so we can track serialization
|
30
|
+
# time as well as ActiveRecord time, etc.:
|
31
|
+
#
|
32
|
+
# Started GET "/" for 127.0.0.1 at 2014-02-12 09:40:29 -0700
|
33
|
+
# Processing by ReleasesController#index as HTML
|
34
|
+
# Rendered releases/_release.html.erb (0.0ms)
|
35
|
+
# Rendered releases/_release.html.erb (0.0ms)
|
36
|
+
# Rendered releases/_release.html.erb (0.0ms)
|
37
|
+
# Rendered releases/_release.html.erb (0.0ms)
|
38
|
+
# Rendered releases/index.html.erb within layouts/application (11.0ms)
|
39
|
+
# Completed 200 OK in 142ms (Views: 117.6ms | ActiveRecord: 1.7ms)
|
40
|
+
#
|
41
|
+
class Instrumenter
|
42
|
+
attr_reader :env
|
43
|
+
|
44
|
+
def flush(env)
|
45
|
+
Protobuf::Logger.info { to_s(env) }
|
46
|
+
end
|
47
|
+
|
48
|
+
def start
|
49
|
+
@start_time = ::Time.now.utc
|
50
|
+
end
|
51
|
+
|
52
|
+
def stop
|
53
|
+
@end_time = ::Time.now.utc
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_s(env)
|
57
|
+
@env = env
|
58
|
+
|
59
|
+
[
|
60
|
+
"[SRV]",
|
61
|
+
env.client_host,
|
62
|
+
env.worker_id,
|
63
|
+
rpc,
|
64
|
+
sizes,
|
65
|
+
elapsed_time,
|
66
|
+
@end_time.try(:iso8601)
|
67
|
+
].compact.join(' - ')
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def elapsed_time
|
73
|
+
(@start_time && @end_time ? "#{(@end_time - @start_time).round(4)}s" : nil)
|
74
|
+
end
|
75
|
+
|
76
|
+
def rpc
|
77
|
+
env.service_name && env.method_name ? "#{env.service_name}##{env.method_name}" : nil
|
78
|
+
end
|
79
|
+
|
80
|
+
def sizes
|
81
|
+
if env.encoded_response?
|
82
|
+
"#{env.encoded_request.size}B/#{env.encoded_response.size}B"
|
83
|
+
else
|
84
|
+
"#{env.encoded_request.size}B/-"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
module Middleware
|
4
|
+
class RequestDecoder
|
5
|
+
include ::Protobuf::Logger::LogMethods
|
6
|
+
|
7
|
+
attr_reader :app, :env
|
8
|
+
|
9
|
+
def initialize(app)
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
@env = env
|
15
|
+
|
16
|
+
env.service_name = service_name
|
17
|
+
env.method_name = method_name
|
18
|
+
env.request = request
|
19
|
+
env.client_host = request_wrapper.caller
|
20
|
+
|
21
|
+
env.rpc_service = service
|
22
|
+
env.rpc_method = rpc_method
|
23
|
+
env.request_type = rpc_method.request_type
|
24
|
+
env.response_type = rpc_method.response_type
|
25
|
+
|
26
|
+
app.call(env)
|
27
|
+
end
|
28
|
+
|
29
|
+
def log_signature
|
30
|
+
env.signature || super
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def method_name
|
36
|
+
@method_name ||= begin
|
37
|
+
method_name = request_wrapper.method_name.underscore.to_sym
|
38
|
+
|
39
|
+
unless service.rpc_method?(method_name)
|
40
|
+
raise MethodNotFound.new("#{service.name}##{method_name} is not a defined RPC method.")
|
41
|
+
end
|
42
|
+
|
43
|
+
method_name
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def request
|
48
|
+
@request ||= begin
|
49
|
+
data = request_wrapper.request_proto
|
50
|
+
rpc_method.request_type.decode(data)
|
51
|
+
end
|
52
|
+
rescue => exception
|
53
|
+
raise BadRequestData.new("Unable to decode request: #{exception.message}")
|
54
|
+
end
|
55
|
+
|
56
|
+
# Decode the incoming request object into our expected request object
|
57
|
+
#
|
58
|
+
def request_wrapper
|
59
|
+
@request_wrapper ||= begin
|
60
|
+
log_debug { sign_message("Decoding request: #{env.encoded_request}") }
|
61
|
+
Socketrpc::Request.decode(env.encoded_request)
|
62
|
+
end
|
63
|
+
rescue => exception
|
64
|
+
raise BadRequestData.new("Unable to decode request: #{exception.message}")
|
65
|
+
end
|
66
|
+
|
67
|
+
def rpc_method
|
68
|
+
@rpc_method ||= service.rpcs[method_name]
|
69
|
+
end
|
70
|
+
|
71
|
+
def service
|
72
|
+
@service ||= service_name.constantize
|
73
|
+
rescue NameError
|
74
|
+
raise ServiceNotFound.new("Service class #{service_name} is not defined.")
|
75
|
+
end
|
76
|
+
|
77
|
+
def service_name
|
78
|
+
@service_name ||= request_wrapper.service_name
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
module Middleware
|
4
|
+
class ResponseEncoder
|
5
|
+
include ::Protobuf::Logger::LogMethods
|
6
|
+
|
7
|
+
attr_reader :app, :env
|
8
|
+
|
9
|
+
def initialize(app)
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
@env = app.call(env)
|
15
|
+
|
16
|
+
env.response = response
|
17
|
+
env.encoded_response = encoded_response
|
18
|
+
env
|
19
|
+
end
|
20
|
+
|
21
|
+
def log_signature
|
22
|
+
env.signature || super
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
# Encode the response wrapper to return to the client
|
28
|
+
#
|
29
|
+
def encoded_response
|
30
|
+
log_debug { sign_message("Encoding response: #{response.inspect}") }
|
31
|
+
|
32
|
+
env.encoded_response = wrapped_response.encode
|
33
|
+
rescue => exception
|
34
|
+
log_exception(exception)
|
35
|
+
|
36
|
+
# Rescue encoding exceptions, re-wrap them as generic protobuf errors,
|
37
|
+
# and re-raise them
|
38
|
+
raise PbError.new(exception.message)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Prod the object to see if we can produce a proto object as a response
|
42
|
+
# candidate. Validate the candidate protos.
|
43
|
+
def response
|
44
|
+
@response ||= begin
|
45
|
+
candidate = env.response
|
46
|
+
case
|
47
|
+
when candidate.is_a?(Message) then
|
48
|
+
validate!(candidate)
|
49
|
+
when candidate.respond_to?(:to_proto) then
|
50
|
+
validate!(candidate.to_proto)
|
51
|
+
when candidate.respond_to?(:to_hash) then
|
52
|
+
env.response_type.new(candidate.to_hash)
|
53
|
+
when candidate.is_a?(PbError) then
|
54
|
+
candidate
|
55
|
+
else
|
56
|
+
validate!(candidate)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Ensure that the response candidate we've been given is of the type
|
62
|
+
# we expect so that deserialization on the client side works.
|
63
|
+
#
|
64
|
+
def validate!(candidate)
|
65
|
+
actual = candidate.class
|
66
|
+
expected = env.response_type
|
67
|
+
|
68
|
+
if expected != actual
|
69
|
+
raise BadResponseProto.new("Expected response to be of type #{expected.name} but was #{actual.name}")
|
70
|
+
end
|
71
|
+
|
72
|
+
candidate
|
73
|
+
end
|
74
|
+
|
75
|
+
# The middleware stack returns either an error or response proto. Package
|
76
|
+
# it up so that it's in the correct spot in the response wrapper
|
77
|
+
#
|
78
|
+
def wrapped_response
|
79
|
+
if response.is_a?(Protobuf::Rpc::PbError)
|
80
|
+
Socketrpc::Response.new(:error => response.message, :error_reason => response.error_type)
|
81
|
+
else
|
82
|
+
Socketrpc::Response.new(:response_proto => response.encode)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'middleware/runner'
|
2
|
+
|
3
|
+
module Protobuf
|
4
|
+
module Rpc
|
5
|
+
module Middleware
|
6
|
+
class Runner < ::Middleware::Runner
|
7
|
+
# Override the default middleware runner so we can ensure that the
|
8
|
+
# service dispatcher is the last thing called in the stack.
|
9
|
+
#
|
10
|
+
def initialize(stack)
|
11
|
+
stack << Protobuf::Rpc::ServiceDispatcher
|
12
|
+
|
13
|
+
super(stack)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'middleware'
|
2
|
+
|
3
|
+
require 'protobuf/rpc/middleware/exception_handler'
|
4
|
+
require 'protobuf/rpc/middleware/logger'
|
5
|
+
require 'protobuf/rpc/middleware/request_decoder'
|
6
|
+
require 'protobuf/rpc/middleware/response_encoder'
|
7
|
+
require 'protobuf/rpc/middleware/runner'
|
8
|
+
|
9
|
+
module Protobuf
|
10
|
+
module Rpc
|
11
|
+
def self.middleware
|
12
|
+
@middleware ||= ::Middleware::Builder.new(:runner_class => ::Protobuf::Rpc::Middleware::Runner)
|
13
|
+
end
|
14
|
+
|
15
|
+
# Ensure the middleware stack is initialized
|
16
|
+
middleware
|
17
|
+
end
|
18
|
+
|
19
|
+
Rpc.middleware.use(Rpc::Middleware::ExceptionHandler)
|
20
|
+
Rpc.middleware.use(Rpc::Middleware::RequestDecoder)
|
21
|
+
Rpc.middleware.use(Rpc::Middleware::Logger)
|
22
|
+
Rpc.middleware.use(Rpc::Middleware::ResponseEncoder)
|
23
|
+
|
24
|
+
ActiveSupport.run_load_hooks(:protobuf_rpc_middleware, Rpc)
|
25
|
+
end
|
data/lib/protobuf/rpc/rpc.pb.rb
CHANGED
@@ -4,9 +4,8 @@
|
|
4
4
|
require 'protobuf/message'
|
5
5
|
|
6
6
|
module Protobuf
|
7
|
-
|
8
7
|
module Socketrpc
|
9
|
-
|
8
|
+
|
10
9
|
##
|
11
10
|
# Enum Classes
|
12
11
|
#
|
@@ -22,33 +21,33 @@ module Protobuf
|
|
22
21
|
define :UNKNOWN_HOST, 8
|
23
22
|
define :IO_ERROR, 9
|
24
23
|
end
|
25
|
-
|
26
|
-
|
24
|
+
|
25
|
+
|
27
26
|
##
|
28
27
|
# Message Classes
|
29
28
|
#
|
30
29
|
class Request < ::Protobuf::Message; end
|
31
30
|
class Response < ::Protobuf::Message; end
|
32
|
-
|
31
|
+
|
32
|
+
|
33
33
|
##
|
34
34
|
# Message Fields
|
35
35
|
#
|
36
36
|
class Request
|
37
|
-
required
|
38
|
-
required
|
39
|
-
optional
|
40
|
-
optional
|
37
|
+
required :string, :service_name, 1
|
38
|
+
required :string, :method_name, 2
|
39
|
+
optional :bytes, :request_proto, 3
|
40
|
+
optional :string, :caller, 4
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
class Response
|
44
|
-
optional
|
45
|
-
optional
|
46
|
-
optional
|
44
|
+
optional :bytes, :response_proto, 1
|
45
|
+
optional :string, :error, 2
|
46
|
+
optional :bool, :callback, 3, :default => false
|
47
47
|
optional ::Protobuf::Socketrpc::ErrorReason, :error_reason, 4
|
48
48
|
end
|
49
|
-
|
50
|
-
|
49
|
+
|
51
50
|
end
|
52
|
-
|
51
|
+
|
53
52
|
end
|
54
53
|
|