protobuf 3.7.0.pre2 → 3.7.0.pre3

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.
Files changed (114) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -1
  3. data/.rubocop_todo.yml +7 -1
  4. data/.travis.yml +8 -1
  5. data/CHANGES.md +25 -1
  6. data/bin/protoc-gen-ruby +2 -2
  7. data/lib/protobuf/cli.rb +29 -17
  8. data/lib/protobuf/code_generator.rb +49 -1
  9. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +9 -1
  10. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +14 -1
  11. data/lib/protobuf/encoder.rb +2 -2
  12. data/lib/protobuf/enum.rb +3 -3
  13. data/lib/protobuf/field/base_field.rb +27 -19
  14. data/lib/protobuf/field/bool_field.rb +10 -8
  15. data/lib/protobuf/field/bytes_field.rb +14 -6
  16. data/lib/protobuf/field/float_field.rb +2 -0
  17. data/lib/protobuf/field/string_field.rb +10 -0
  18. data/lib/protobuf/field/varint_field.rb +12 -2
  19. data/lib/protobuf/generators/base.rb +29 -14
  20. data/lib/protobuf/generators/enum_generator.rb +4 -7
  21. data/lib/protobuf/generators/field_generator.rb +17 -4
  22. data/lib/protobuf/generators/file_generator.rb +121 -10
  23. data/lib/protobuf/generators/group_generator.rb +9 -3
  24. data/lib/protobuf/generators/message_generator.rb +8 -2
  25. data/lib/protobuf/generators/option_generator.rb +17 -0
  26. data/lib/protobuf/generators/printable.rb +2 -2
  27. data/lib/protobuf/generators/service_generator.rb +27 -3
  28. data/lib/protobuf/lifecycle.rb +1 -1
  29. data/lib/protobuf/message/fields.rb +13 -15
  30. data/lib/protobuf/message/serialization.rb +9 -9
  31. data/lib/protobuf/message.rb +23 -29
  32. data/lib/protobuf/optionable.rb +10 -10
  33. data/lib/protobuf/rpc/buffer.rb +7 -6
  34. data/lib/protobuf/rpc/client.rb +2 -30
  35. data/lib/protobuf/rpc/connectors/base.rb +168 -6
  36. data/lib/protobuf/rpc/connectors/ping.rb +2 -2
  37. data/lib/protobuf/rpc/connectors/socket.rb +6 -1
  38. data/lib/protobuf/rpc/connectors/zmq.rb +1 -2
  39. data/lib/protobuf/rpc/dynamic_discovery.pb.rb +2 -1
  40. data/lib/protobuf/rpc/error.rb +2 -2
  41. data/lib/protobuf/rpc/middleware/exception_handler.rb +4 -0
  42. data/lib/protobuf/rpc/middleware/logger.rb +4 -0
  43. data/lib/protobuf/rpc/middleware/request_decoder.rb +11 -16
  44. data/lib/protobuf/rpc/middleware/response_encoder.rb +18 -23
  45. data/lib/protobuf/rpc/rpc.pb.rb +2 -1
  46. data/lib/protobuf/rpc/rpc_method.rb +16 -0
  47. data/lib/protobuf/rpc/servers/socket/server.rb +4 -4
  48. data/lib/protobuf/rpc/servers/socket_runner.rb +8 -0
  49. data/lib/protobuf/rpc/servers/zmq/broker.rb +7 -6
  50. data/lib/protobuf/rpc/servers/zmq/server.rb +8 -7
  51. data/lib/protobuf/rpc/servers/zmq/util.rb +6 -6
  52. data/lib/protobuf/rpc/servers/zmq/worker.rb +7 -6
  53. data/lib/protobuf/rpc/servers/zmq_runner.rb +8 -0
  54. data/lib/protobuf/rpc/service.rb +6 -15
  55. data/lib/protobuf/rpc/service_directory.rb +1 -1
  56. data/lib/protobuf/rpc/service_dispatcher.rb +5 -6
  57. data/lib/protobuf/rpc/service_filters.rb +8 -30
  58. data/lib/protobuf/socket.rb +2 -2
  59. data/lib/protobuf/version.rb +1 -1
  60. data/lib/protobuf/zmq.rb +2 -2
  61. data/lib/protobuf.rb +12 -27
  62. data/protobuf.gemspec +5 -3
  63. data/spec/benchmark/tasks.rb +1 -0
  64. data/spec/functional/code_generator_spec.rb +38 -0
  65. data/spec/lib/protobuf/cli_spec.rb +19 -10
  66. data/spec/lib/protobuf/code_generator_spec.rb +28 -0
  67. data/spec/lib/protobuf/enum_spec.rb +6 -2
  68. data/spec/lib/protobuf/field/bool_field_spec.rb +4 -0
  69. data/spec/lib/protobuf/field/double_field_spec.rb +9 -0
  70. data/spec/lib/protobuf/field/fixed32_field_spec.rb +7 -0
  71. data/spec/lib/protobuf/field/fixed64_field_spec.rb +7 -0
  72. data/spec/lib/protobuf/field/float_field_spec.rb +5 -1
  73. data/spec/lib/protobuf/field/int64_field_spec.rb +7 -0
  74. data/spec/lib/protobuf/field/message_field_spec.rb +53 -0
  75. data/spec/lib/protobuf/field/sfixed32_field_spec.rb +9 -0
  76. data/spec/lib/protobuf/field/sfixed64_field_spec.rb +9 -0
  77. data/spec/lib/protobuf/field/sint32_field_spec.rb +9 -0
  78. data/spec/lib/protobuf/field/sint64_field_spec.rb +9 -0
  79. data/spec/lib/protobuf/field/uint32_field_spec.rb +7 -0
  80. data/spec/lib/protobuf/field/uint64_field_spec.rb +7 -0
  81. data/spec/lib/protobuf/generators/base_spec.rb +69 -1
  82. data/spec/lib/protobuf/generators/enum_generator_spec.rb +1 -1
  83. data/spec/lib/protobuf/generators/field_generator_spec.rb +58 -0
  84. data/spec/lib/protobuf/generators/file_generator_spec.rb +47 -0
  85. data/spec/lib/protobuf/generators/service_generator_spec.rb +58 -14
  86. data/spec/lib/protobuf/message_spec.rb +2 -2
  87. data/spec/lib/protobuf/optionable_spec.rb +96 -0
  88. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +151 -0
  89. data/spec/lib/protobuf/rpc/connectors/ping_spec.rb +3 -3
  90. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +0 -2
  91. data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +2 -2
  92. data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +4 -4
  93. data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +2 -2
  94. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +1 -18
  95. data/spec/lib/protobuf/rpc/service_filters_spec.rb +2 -2
  96. data/spec/lib/protobuf/varint_spec.rb +1 -1
  97. data/spec/lib/protobuf_spec.rb +13 -16
  98. data/spec/support/packed_field.rb +3 -2
  99. data/spec/support/protos/enum.pb.rb +2 -1
  100. data/spec/support/protos/enum.proto +1 -0
  101. data/spec/support/protos/google_unittest.pb.rb +69 -58
  102. data/spec/support/protos/google_unittest_custom_options.bin +0 -0
  103. data/spec/support/protos/google_unittest_custom_options.pb.rb +361 -0
  104. data/spec/support/protos/google_unittest_custom_options.proto +424 -0
  105. data/spec/support/protos/google_unittest_import.pb.rb +8 -0
  106. data/spec/support/protos/google_unittest_import_public.pb.rb +6 -0
  107. data/spec/support/protos/resource.pb.rb +54 -2
  108. data/spec/support/protos/resource.proto +42 -2
  109. data/spec/support/server.rb +1 -1
  110. metadata +39 -16
  111. data/lib/protobuf/rpc/connector.rb +0 -19
  112. data/lib/protobuf/rpc/connectors/common.rb +0 -176
  113. data/spec/lib/protobuf/rpc/connector_spec.rb +0 -26
  114. data/spec/lib/protobuf/rpc/connectors/common_spec.rb +0 -170
@@ -10,11 +10,12 @@ module Protobuf
10
10
  # are accessing options correctly. We allow simple names in other places for backwards compatibility.
11
11
  fail ArgumentError, "must access option using its fully qualified name: #{option.fully_qualified_name.inspect}"
12
12
  end
13
- if @_optionable_options.try(:key?, name)
14
- value = @_optionable_options[name]
15
- else
16
- value = option.default_value
17
- end
13
+ value =
14
+ if @_optionable_options.try(:key?, name)
15
+ @_optionable_options[name]
16
+ else
17
+ option.default_value
18
+ end
18
19
  if option.type_class < ::Protobuf::Message
19
20
  option.type_class.new(value)
20
21
  else
@@ -51,11 +52,10 @@ module Protobuf
51
52
  # File options are injected per module, and since a module can be defined more than once,
52
53
  # we will get a warning if we try to define optionable_descriptor_class twice.
53
54
  if base_class.respond_to?(:optionable_descriptor_class)
54
- if base_class.optionable_descriptor_class != block.call
55
- fail 'A class is being defined with two different descriptor classes, something is very wrong'
56
- else
57
- return # Don't define optionable_descriptor_class twice
58
- end
55
+ # Don't define optionable_descriptor_class twice
56
+ return if base_class.optionable_descriptor_class == block.call
57
+
58
+ fail 'A class is being defined with two different descriptor classes, something is very wrong'
59
59
  end
60
60
 
61
61
  base_class.extend(ClassMethods)
@@ -4,7 +4,7 @@ module Protobuf
4
4
 
5
5
  attr_accessor :mode, :data, :size
6
6
 
7
- MODES = [:read, :write]
7
+ MODES = [:read, :write].freeze
8
8
 
9
9
  # constantize this so we don't re-initialize the regex every time we need it
10
10
  SIZE_REGEX = /^\d+-/
@@ -17,11 +17,12 @@ module Protobuf
17
17
  end
18
18
 
19
19
  def mode=(mode)
20
- if MODES.include?(mode)
21
- @mode = mode
22
- else
23
- @mode = :read
24
- end
20
+ @mode =
21
+ if MODES.include?(mode)
22
+ mode
23
+ else
24
+ :read
25
+ end
25
26
  end
26
27
 
27
28
  def write(force_mode = true)
@@ -2,7 +2,6 @@ require 'forwardable'
2
2
  require 'protobuf'
3
3
  require 'protobuf/logging'
4
4
  require 'protobuf/rpc/error'
5
- require 'protobuf/rpc/connector'
6
5
 
7
6
  module Protobuf
8
7
  module Rpc
@@ -10,7 +9,7 @@ module Protobuf
10
9
  extend Forwardable
11
10
  include Protobuf::Logging
12
11
 
13
- def_delegators :@connector, :options, :complete_cb, :success_cb, :failure_cb
12
+ def_delegators :@connector, :options, :complete_cb, :success_cb, :failure_cb, :send_request
14
13
  attr_reader :connector
15
14
 
16
15
  # Create a new client with default options (defined in ClientConnection)
@@ -28,7 +27,7 @@ module Protobuf
28
27
  #
29
28
  def initialize(options = {})
30
29
  fail "Invalid client configuration. Service must be defined." if options[:service].nil?
31
- @connector = Connector.connector_for_client.new(options)
30
+ @connector = ::Protobuf.connector_type_class.new(options)
32
31
  logger.debug { sign_message("Initialized with options: #{options.inspect}") }
33
32
  end
34
33
 
@@ -134,33 +133,6 @@ module Protobuf
134
133
  end
135
134
  end
136
135
 
137
- # Send the request to the service.
138
- # This method is usually never called directly
139
- # but is invoked by method_missing (see docs above).
140
- #
141
- # request = WidgetFindRequest.new
142
- # client = Client.new({
143
- # :service => WidgetService,
144
- # :method => "find",
145
- # :request_type => "WidgetFindRequest",
146
- # :response_type => "WidgetList",
147
- # :request => request
148
- # })
149
- #
150
- # client.on_success do |res|
151
- # res.widgets.each{|w| puts w.inspect }
152
- # end
153
- #
154
- # client.on_failure do |err|
155
- # puts err.message
156
- # end
157
- #
158
- # client.send_request
159
- #
160
- def send_request
161
- @connector.send_request
162
- end
163
-
164
136
  end
165
137
 
166
138
  ActiveSupport.run_load_hooks(:protobuf_rpc_client, Client)
@@ -4,7 +4,6 @@ require 'protobuf/rpc/rpc.pb'
4
4
  require 'protobuf/rpc/buffer'
5
5
  require 'protobuf/rpc/error'
6
6
  require 'protobuf/rpc/stat'
7
- require 'protobuf/rpc/connectors/common'
8
7
 
9
8
  module Protobuf
10
9
  module Rpc
@@ -20,26 +19,113 @@ module Protobuf
20
19
  :timeout => nil, # The timeout for the request, also handled by client.rb
21
20
  :client_host => nil, # The hostname or address of this client
22
21
  :first_alive_load_balance => false, # Do we want to use check_avail frames before request
23
- }
22
+ }.freeze
24
23
 
25
24
  class Base
26
25
  include Protobuf::Logging
27
26
 
28
- attr_reader :options
29
- attr_accessor :success_cb, :failure_cb, :complete_cb
27
+ attr_reader :options, :error
28
+ attr_accessor :success_cb, :failure_cb, :complete_cb, :stats
30
29
 
31
30
  def initialize(options)
32
31
  @options = DEFAULT_OPTIONS.merge(options)
33
32
  @stats = ::Protobuf::Rpc::Stat.new(:CLIENT)
34
33
  end
35
34
 
35
+ def any_callbacks?
36
+ [@complete_cb, @failure_cb, @success_cb].any?
37
+ end
38
+
39
+ def close_connection
40
+ fail 'If you inherit a Connector from Base you must implement close_connection'
41
+ end
42
+
43
+ def complete
44
+ @stats.stop
45
+ logger.info { @stats.to_s }
46
+ logger.debug { sign_message('Response proceessing complete') }
47
+ @complete_cb.call(self) unless @complete_cb.nil?
48
+ rescue => e
49
+ logger.error { sign_message('Complete callback error encountered') }
50
+ log_exception(e)
51
+ raise
52
+ end
53
+
54
+ def data_callback(data)
55
+ logger.debug { sign_message('Using data_callback') }
56
+ @used_data_callback = true
57
+ @data = data
58
+ end
59
+
60
+ # All failures should be routed through this method.
61
+ #
62
+ # @param [Symbol] code The code we're using (see ::Protobuf::Socketrpc::ErrorReason)
63
+ # @param [String] message The error message
64
+ def failure(code, message)
65
+ @error = ClientError.new
66
+ @error.code = ::Protobuf::Socketrpc::ErrorReason.fetch(code)
67
+ @error.message = message
68
+ logger.debug { sign_message("Server failed request (invoking on_failure): #{@error.inspect}") }
69
+
70
+ @failure_cb.call(@error) unless @failure_cb.nil?
71
+ rescue => e
72
+ logger.error { sign_message("Failure callback error encountered") }
73
+ log_exception(e)
74
+ raise
75
+ ensure
76
+ complete
77
+ end
78
+
36
79
  def first_alive_load_balance?
37
80
  ENV.key?("PB_FIRST_ALIVE_LOAD_BALANCE") ||
38
81
  options[:first_alive_load_balance]
39
82
  end
40
83
 
41
- def send_request
42
- fail 'If you inherit a Connector from Base you must implement send_request'
84
+ def initialize_stats
85
+ @stats = ::Protobuf::Rpc::Stat.new(:CLIENT)
86
+ @stats.server = [@options[:port], @options[:host]]
87
+ @stats.service = @options[:service].name
88
+ @stats.method_name = @options[:method].to_s
89
+ rescue => ex
90
+ log_exception(ex)
91
+ failure(:RPC_ERROR, "Invalid stats configuration. #{ex.message}")
92
+ end
93
+
94
+ def log_signature
95
+ @_log_signature ||= "[client-#{self.class}]"
96
+ end
97
+
98
+ def parse_response
99
+ # Close up the connection as we no longer need it
100
+ close_connection
101
+
102
+ logger.debug { sign_message("Parsing response from server (connection closed)") }
103
+
104
+ # Parse out the raw response
105
+ @stats.response_size = @response_data.size unless @response_data.nil?
106
+ response_wrapper = ::Protobuf::Socketrpc::Response.decode(@response_data)
107
+
108
+ # Determine success or failure based on parsed data
109
+ if response_wrapper.field?(:error_reason)
110
+ logger.debug { sign_message("Error response parsed") }
111
+
112
+ # fail the call if we already know the client is failed
113
+ # (don't try to parse out the response payload)
114
+ failure(response_wrapper.error_reason, response_wrapper.error)
115
+ else
116
+ logger.debug { sign_message("Successful response parsed") }
117
+
118
+ # Ensure client_response is an instance
119
+ parsed = @options[:response_type].decode(response_wrapper.response_proto.to_s)
120
+
121
+ if parsed.nil? && !response_wrapper.field?(:error_reason)
122
+ failure(:BAD_RESPONSE_PROTO, 'Unable to parse response from server')
123
+ else
124
+ verify_callbacks
125
+ succeed(parsed)
126
+ return @data if @used_data_callback
127
+ end
128
+ end
43
129
  end
44
130
 
45
131
  def ping_port
@@ -49,6 +135,82 @@ module Protobuf
49
135
  def ping_port_enabled?
50
136
  ENV.key?("PB_RPC_PING_PORT")
51
137
  end
138
+
139
+ def request_bytes
140
+ validate_request_type!
141
+ fields = { :service_name => @options[:service].name,
142
+ :method_name => @options[:method].to_s,
143
+ :request_proto => @options[:request],
144
+ :caller => request_caller }
145
+
146
+ return ::Protobuf::Socketrpc::Request.encode(fields)
147
+ rescue => e
148
+ failure(:INVALID_REQUEST_PROTO, "Could not set request proto: #{e.message}")
149
+ end
150
+
151
+ def request_caller
152
+ @options[:client_host] || ::Protobuf.client_host
153
+ end
154
+
155
+ def send_request
156
+ fail 'If you inherit a Connector from Base you must implement send_request'
157
+ end
158
+
159
+ def setup_connection
160
+ initialize_stats
161
+ @request_data = request_bytes
162
+ @stats.request_size = @request_data.size
163
+ end
164
+
165
+ def succeed(response)
166
+ logger.debug { sign_message("Server succeeded request (invoking on_success)") }
167
+ @success_cb.call(response) unless @success_cb.nil?
168
+ rescue => e
169
+ logger.error { sign_message("Success callback error encountered") }
170
+ log_exception(e)
171
+ failure(:RPC_ERROR, "An exception occurred while calling on_success: #{e.message}")
172
+ ensure
173
+ complete
174
+ end
175
+
176
+ def timeout
177
+ if options[:timeout]
178
+ options[:timeout]
179
+ else
180
+ 300 # seconds
181
+ end
182
+ end
183
+
184
+ # Wrap the given block in a timeout of the configured number of seconds.
185
+ #
186
+ def timeout_wrap(&block)
187
+ ::Timeout.timeout(timeout, &block)
188
+ rescue ::Timeout::Error
189
+ failure(:RPC_FAILED, "The server took longer than #{timeout} seconds to respond")
190
+ end
191
+
192
+ def validate_request_type!
193
+ unless @options[:request].class == @options[:request_type]
194
+ expected = @options[:request_type].name
195
+ actual = @options[:request].class.name
196
+ failure(:INVALID_REQUEST_PROTO, "Expected request type to be type of #{expected}, got #{actual} instead")
197
+ end
198
+ end
199
+
200
+ def verify_callbacks
201
+ unless any_callbacks?
202
+ logger.debug { sign_message("No callbacks set, using data_callback") }
203
+ @success_cb = @failure_cb = method(:data_callback)
204
+ end
205
+ end
206
+
207
+ def verify_options!
208
+ # Verify the options that are necessary and merge them in
209
+ [:service, :method, :host, :port].each do |opt|
210
+ failure(:RPC_ERROR, "Invalid client connection configuration. #{opt} must be a defined option.") if @options[opt].nil?
211
+ end
212
+ end
213
+
52
214
  end
53
215
  end
54
216
  end
@@ -29,9 +29,9 @@ module Protobuf
29
29
  def timeout
30
30
  @timeout ||= begin
31
31
  if ::ENV.key?("PB_RPC_PING_PORT_TIMEOUT")
32
- ::ENV["PB_RPC_PING_PORT_TIMEOUT"].to_i
32
+ ::ENV["PB_RPC_PING_PORT_TIMEOUT"].to_f / 1000
33
33
  else
34
- 5 # 5 seconds
34
+ 0.2 # 200 ms
35
35
  end
36
36
  end
37
37
  end
@@ -4,7 +4,6 @@ module Protobuf
4
4
  module Rpc
5
5
  module Connectors
6
6
  class Socket < Base
7
- include Protobuf::Rpc::Connectors::Common
8
7
  include Protobuf::Logging
9
8
 
10
9
  def send_request
@@ -39,6 +38,12 @@ module Protobuf
39
38
  @socket.closed?
40
39
  end
41
40
 
41
+ def post_init
42
+ send_data unless error?
43
+ rescue => e
44
+ failure(:RPC_ERROR, "Connection error: #{e.message}")
45
+ end
46
+
42
47
  def read_data
43
48
  size_io = StringIO.new
44
49
 
@@ -14,7 +14,6 @@ module Protobuf
14
14
  ##
15
15
  # Included Modules
16
16
  #
17
- include Protobuf::Rpc::Connectors::Common
18
17
  include Protobuf::Logging
19
18
 
20
19
  ##
@@ -271,7 +270,7 @@ module Protobuf
271
270
  def zmq_eagain_error_check(return_code, source)
272
271
  return if ::ZMQ::Util.resultcode_ok?(return_code || -1)
273
272
 
274
- if ::ZMQ::Util.errno == ::ZMQ::EAGAIN
273
+ if ::ZMQ::Util.errno == ::ZMQ::EAGAIN # rubocop:disable Style/GuardClause
275
274
  fail ZmqEagainError, <<-ERROR
276
275
  Last ZMQ API call to #{source} failed with "#{::ZMQ::Util.error_string}".
277
276
 
@@ -3,11 +3,12 @@
3
3
  ##
4
4
  # This file is auto-generated. DO NOT EDIT!
5
5
  #
6
- require 'protobuf/message'
6
+ require 'protobuf'
7
7
 
8
8
  module Protobuf
9
9
  module Rpc
10
10
  module DynamicDiscovery
11
+ ::Protobuf::Optionable.inject(self) { ::Google::Protobuf::FileOptions }
11
12
 
12
13
  ##
13
14
  # Enum Classes
@@ -9,7 +9,7 @@ module Protobuf
9
9
  attr_reader :error_type
10
10
 
11
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
12
+ @error_type = error_type.is_a?(String) ? ::Protobuf::Socketrpc::ErrorReason.const_get(error_type) : error_type
13
13
  super message
14
14
  end
15
15
 
@@ -18,7 +18,7 @@ module Protobuf
18
18
  end
19
19
 
20
20
  def to_response
21
- Socketrpc::Response.new(:error => message, :error_reason => error_type)
21
+ ::Protobuf::Socketrpc::Response.new(:error => message, :error_reason => error_type)
22
22
  end
23
23
  end
24
24
  end
@@ -11,6 +11,10 @@ module Protobuf
11
11
  end
12
12
 
13
13
  def call(env)
14
+ dup._call(env)
15
+ end
16
+
17
+ def _call(env)
14
18
  app.call(env)
15
19
  rescue => exception
16
20
  log_exception(exception)
@@ -8,6 +8,10 @@ module Protobuf
8
8
 
9
9
  # TODO: Figure out how to control when logs are flushed
10
10
  def call(env)
11
+ dup._call(env)
12
+ end
13
+
14
+ def _call(env)
11
15
  instrumenter.start
12
16
  instrumenter.flush(env) # Log request stats
13
17
 
@@ -11,8 +11,13 @@ module Protobuf
11
11
  end
12
12
 
13
13
  def call(env)
14
+ dup._call(env)
15
+ end
16
+
17
+ def _call(env)
14
18
  @env = env
15
19
 
20
+ logger.debug { sign_message("Decoding request: #{env.encoded_request}") }
16
21
  env.service_name = service_name
17
22
  env.method_name = method_name
18
23
  env.request = request
@@ -33,22 +38,15 @@ module Protobuf
33
38
  private
34
39
 
35
40
  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
- fail MethodNotFound, "#{service.name}##{method_name} is not a defined RPC method."
41
- end
41
+ return @method_name unless @method_name.nil?
42
42
 
43
- method_name
44
- end
43
+ @method_name = request_wrapper.method_name.underscore.to_sym
44
+ fail MethodNotFound, "#{service.name}##{@method_name} is not a defined RPC method." unless service.rpc_method?(@method_name)
45
+ @method_name
45
46
  end
46
47
 
47
48
  def request
48
- @request ||= begin
49
- data = request_wrapper.request_proto
50
- rpc_method.request_type.decode(data)
51
- end
49
+ @request ||= rpc_method.request_type.decode(request_wrapper.request_proto)
52
50
  rescue => exception
53
51
  raise BadRequestData, "Unable to decode request: #{exception.message}"
54
52
  end
@@ -56,10 +54,7 @@ module Protobuf
56
54
  # Decode the incoming request object into our expected request object
57
55
  #
58
56
  def request_wrapper
59
- @request_wrapper ||= begin
60
- logger.debug { sign_message("Decoding request: #{env.encoded_request}") }
61
- Socketrpc::Request.decode(env.encoded_request)
62
- end
57
+ @request_wrapper ||= ::Protobuf::Socketrpc::Request.decode(env.encoded_request)
63
58
  rescue => exception
64
59
  raise BadRequestData, "Unable to decode request: #{exception.message}"
65
60
  end
@@ -11,6 +11,10 @@ module Protobuf
11
11
  end
12
12
 
13
13
  def call(env)
14
+ dup._call(env)
15
+ end
16
+
17
+ def _call(env)
14
18
  @env = app.call(env)
15
19
 
16
20
  env.response = response
@@ -41,32 +45,23 @@ module Protobuf
41
45
  # Prod the object to see if we can produce a proto object as a response
42
46
  # candidate. Validate the candidate protos.
43
47
  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
48
+ return @response unless @response.nil?
49
+
50
+ candidate = env.response
51
+ return @response = validate!(candidate) if candidate.is_a?(Message)
52
+ return @response = validate!(candidate.to_proto) if candidate.respond_to?(:to_proto)
53
+ return @response = env.response_type.new(candidate.to_hash) if candidate.respond_to?(:to_hash)
54
+ return @response = candidate if candidate.is_a?(PbError)
55
+
56
+ @response = validate!(candidate)
59
57
  end
60
58
 
61
59
  # Ensure that the response candidate we've been given is of the type
62
60
  # we expect so that deserialization on the client side works.
63
61
  #
64
62
  def validate!(candidate)
65
- actual = candidate.class
66
- expected = env.response_type
67
-
68
- if expected != actual
69
- fail BadResponseProto, "Expected response to be of type #{expected.name} but was #{actual.name}"
63
+ if candidate.class != env.response_type
64
+ fail BadResponseProto, "Expected response to be of type #{env.response_type.name} but was #{candidate.class.name}"
70
65
  end
71
66
 
72
67
  candidate
@@ -76,10 +71,10 @@ module Protobuf
76
71
  # it up so that it's in the correct spot in the response wrapper
77
72
  #
78
73
  def wrapped_response
79
- if response.is_a?(Protobuf::Rpc::PbError)
80
- Socketrpc::Response.new(:error => response.message, :error_reason => response.error_type)
74
+ if response.is_a?(::Protobuf::Rpc::PbError)
75
+ ::Protobuf::Socketrpc::Response.new(:error => response.message, :error_reason => response.error_type)
81
76
  else
82
- Socketrpc::Response.new(:response_proto => response.encode)
77
+ ::Protobuf::Socketrpc::Response.new(:response_proto => response.encode)
83
78
  end
84
79
  end
85
80
  end
@@ -3,10 +3,11 @@
3
3
  ##
4
4
  # This file is auto-generated. DO NOT EDIT!
5
5
  #
6
- require 'protobuf/message'
6
+ require 'protobuf'
7
7
 
8
8
  module Protobuf
9
9
  module Socketrpc
10
+ ::Protobuf::Optionable.inject(self) { ::Google::Protobuf::FileOptions }
10
11
 
11
12
  ##
12
13
  # Enum Classes
@@ -0,0 +1,16 @@
1
+ module Protobuf
2
+ module Rpc
3
+ class RpcMethod
4
+ ::Protobuf::Optionable.inject(self, false) { ::Google::Protobuf::MethodOptions }
5
+
6
+ attr_reader :method, :request_type, :response_type
7
+
8
+ def initialize(method, request_type, response_type, &options_block)
9
+ @method = method
10
+ @request_type = request_type
11
+ @response_type = response_type
12
+ instance_eval(&options_block) if options_block
13
+ end
14
+ end
15
+ end
16
+ end
@@ -18,7 +18,7 @@ module Protobuf
18
18
  public
19
19
 
20
20
  attr_reader :running
21
- alias_method :running?, :running
21
+ alias :running? running
22
22
 
23
23
  def initialize(options)
24
24
  self.running = false
@@ -38,7 +38,7 @@ module Protobuf
38
38
 
39
39
  def cleanup?
40
40
  # every `threshold` connections run a cleanup routine after closing the response
41
- threads.size > 0 && threads.size % threshold == 0
41
+ !threads.empty? && threads.size % threshold == 0
42
42
  end
43
43
 
44
44
  def cleanup_threads
@@ -102,9 +102,9 @@ module Protobuf
102
102
  end
103
103
  end
104
104
  end
105
- else
105
+ elsif threads.size > 1
106
106
  # Run a cleanup if select times out while waiting
107
- cleanup_threads if threads.size > 1
107
+ cleanup_threads
108
108
  end
109
109
  end
110
110
  ensure
@@ -36,3 +36,11 @@ module Protobuf
36
36
  end
37
37
  end
38
38
  end
39
+
40
+ module Protobuf
41
+ module Rpc
42
+ module Servers # bad file namespacing
43
+ SocketRunner = ::Protobuf::Rpc::SocketRunner
44
+ end
45
+ end
46
+ end
@@ -107,11 +107,12 @@ module Protobuf
107
107
  end
108
108
 
109
109
  def init_zmq_context
110
- if inproc?
111
- @zmq_context = @server.zmq_context
112
- else
113
- @zmq_context = ZMQ::Context.new
114
- end
110
+ @zmq_context =
111
+ if inproc?
112
+ @server.zmq_context
113
+ else
114
+ ZMQ::Context.new
115
+ end
115
116
  end
116
117
 
117
118
  def inproc?
@@ -146,7 +147,7 @@ module Protobuf
146
147
  write_to_frontend([address, ::Protobuf::Rpc::Zmq::EMPTY_STRING, ::Protobuf::Rpc::Zmq::NO_WORKERS_AVAILABLE])
147
148
  end
148
149
  else
149
- if @idle_workers.empty?
150
+ if @idle_workers.empty? # rubocop:disable Style/IfInsideElse
150
151
  local_queue << [address, ::Protobuf::Rpc::Zmq::EMPTY_STRING, message].concat(frames)
151
152
  else
152
153
  write_to_backend([@idle_workers.shift, ::Protobuf::Rpc::Zmq::EMPTY_STRING].concat([address, ::Protobuf::Rpc::Zmq::EMPTY_STRING, message]).concat(frames))