protobuf 3.2.1 → 3.3.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/lib/protobuf/cli.rb +17 -13
- data/lib/protobuf/field/base_field.rb +3 -1
- data/lib/protobuf/field/bytes_field.rb +2 -2
- data/lib/protobuf/lifecycle.rb +1 -1
- data/lib/protobuf/logging.rb +49 -0
- data/lib/protobuf/rpc/client.rb +10 -10
- data/lib/protobuf/rpc/connectors/base.rb +2 -2
- data/lib/protobuf/rpc/connectors/common.rb +12 -12
- data/lib/protobuf/rpc/connectors/socket.rb +6 -6
- data/lib/protobuf/rpc/connectors/zmq.rb +11 -9
- data/lib/protobuf/rpc/middleware/exception_handler.rb +1 -1
- data/lib/protobuf/rpc/middleware/logger.rb +1 -1
- data/lib/protobuf/rpc/middleware/request_decoder.rb +3 -3
- data/lib/protobuf/rpc/middleware/response_encoder.rb +3 -3
- data/lib/protobuf/rpc/server.rb +1 -1
- data/lib/protobuf/rpc/servers/socket/server.rb +7 -7
- data/lib/protobuf/rpc/servers/socket/worker.rb +2 -2
- data/lib/protobuf/rpc/servers/zmq/broker.rb +9 -5
- data/lib/protobuf/rpc/servers/zmq/server.rb +3 -3
- data/lib/protobuf/rpc/servers/zmq/util.rb +1 -1
- data/lib/protobuf/rpc/servers/zmq_runner.rb +4 -4
- data/lib/protobuf/rpc/service.rb +2 -2
- data/lib/protobuf/rpc/service_directory.rb +8 -8
- data/lib/protobuf/rpc/service_dispatcher.rb +2 -2
- data/lib/protobuf/rpc/stat.rb +1 -1
- data/lib/protobuf/version.rb +1 -1
- data/spec/benchmark/tasks.rb +2 -2
- data/spec/lib/protobuf/cli_spec.rb +9 -3
- data/spec/spec_helper.rb +6 -5
- data/spec/support/server.rb +3 -3
- metadata +64 -106
- checksums.yaml +0 -7
- data/lib/protobuf/logger.rb +0 -86
- data/spec/lib/protobuf/logger_spec.rb +0 -136
data/lib/protobuf/cli.rb
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require 'protobuf/version'
|
3
|
-
require 'protobuf/
|
3
|
+
require 'protobuf/logging'
|
4
4
|
require 'protobuf/rpc/servers/socket_runner'
|
5
5
|
require 'protobuf/rpc/servers/zmq_runner'
|
6
6
|
|
7
7
|
module Protobuf
|
8
8
|
class CLI < ::Thor
|
9
9
|
include ::Thor::Actions
|
10
|
+
include ::Protobuf::Logging
|
10
11
|
|
11
12
|
attr_accessor :runner, :mode
|
12
13
|
|
@@ -21,7 +22,7 @@ module Protobuf
|
|
21
22
|
option :threshold, :type => :numeric, :default => 100, :aliases => %w(-t), :desc => 'Multi-threaded Socket Server cleanup threshold.'
|
22
23
|
option :threads, :type => :numeric, :default => 5, :aliases => %w(-r), :desc => 'Number of worker threads to run. Only applicable in --zmq mode.'
|
23
24
|
|
24
|
-
option :log, :type => :string, :aliases => %w(-l), :desc => 'Log file or device. Default is STDOUT.'
|
25
|
+
option :log, :type => :string, :default => STDOUT, :aliases => %w(-l), :desc => 'Log file or device. Default is STDOUT.'
|
25
26
|
option :level, :type => :numeric, :default => ::Logger::INFO, :aliases => %w(-v), :desc => 'Log level to use, 0-5 (see http://www.ruby-doc.org/stdlib/libdoc/logger/rdoc/)'
|
26
27
|
|
27
28
|
option :socket, :type => :boolean, :aliases => %w(-s), :desc => 'Socket Mode for server and client connections.'
|
@@ -86,12 +87,14 @@ module Protobuf
|
|
86
87
|
# Setup the protobuf logger.
|
87
88
|
def configure_logger
|
88
89
|
debug_say('Configuring logger')
|
89
|
-
|
90
|
-
|
90
|
+
|
91
|
+
log_level = options.debug? ? ::Logger::DEBUG : options.level
|
92
|
+
|
93
|
+
::Protobuf::Logging.initialize_logger(options.log, log_level)
|
91
94
|
|
92
95
|
# Debug output the server options to the log file.
|
93
|
-
|
94
|
-
|
96
|
+
logger.debug { 'Debugging options:' }
|
97
|
+
logger.debug { options.inspect }
|
95
98
|
end
|
96
99
|
|
97
100
|
# Re-write the $0 var to have a nice process name in ps.
|
@@ -185,15 +188,16 @@ module Protobuf
|
|
185
188
|
end
|
186
189
|
|
187
190
|
def say_and_exit(message, exception = nil)
|
188
|
-
message = set_color(message, :red) if
|
191
|
+
message = set_color(message, :red) if options.log == STDOUT
|
192
|
+
|
193
|
+
logger.error { message }
|
189
194
|
|
190
|
-
::Protobuf::Logger.error { message }
|
191
195
|
if exception
|
192
196
|
$stderr.puts "[#{exception.class.name}] #{exception.message}"
|
193
197
|
$stderr.puts exception.backtrace.join("\n")
|
194
198
|
|
195
|
-
|
196
|
-
|
199
|
+
logger.error { "[#{exception.class.name}] #{exception.message}" }
|
200
|
+
logger.debug { exception.backtrace.join("\n") }
|
197
201
|
end
|
198
202
|
|
199
203
|
exit(1)
|
@@ -212,10 +216,10 @@ module Protobuf
|
|
212
216
|
end
|
213
217
|
|
214
218
|
def shutdown_server
|
215
|
-
|
219
|
+
logger.info { 'RPC Server shutting down...' }
|
216
220
|
@runner.try(:stop)
|
217
221
|
::Protobuf::Rpc::ServiceDirectory.instance.stop
|
218
|
-
|
222
|
+
logger.info { 'Shutdown complete' }
|
219
223
|
end
|
220
224
|
|
221
225
|
# Start the runner and log the relevant options.
|
@@ -223,7 +227,7 @@ module Protobuf
|
|
223
227
|
debug_say('Running server')
|
224
228
|
|
225
229
|
@runner.run do
|
226
|
-
|
230
|
+
logger.info {
|
227
231
|
"pid #{::Process.pid} -- #{@runner_mode} RPC Server listening at #{options.host}:#{options.port}"
|
228
232
|
}
|
229
233
|
|
@@ -67,8 +67,8 @@ module Protobuf
|
|
67
67
|
raise TypeError, "Unacceptable value #{val} for field #{field.name} of type #{field.type_class}"
|
68
68
|
end
|
69
69
|
rescue NoMethodError => ex
|
70
|
-
|
71
|
-
|
70
|
+
logger.error { ex.message }
|
71
|
+
logger.error { ex.backtrace.join("\n") }
|
72
72
|
raise TypeError, "Got NoMethodError attempting to set #{val} for field #{field.name} of type #{field.type_class}: #{ex.message}"
|
73
73
|
end
|
74
74
|
end
|
data/lib/protobuf/lifecycle.rb
CHANGED
@@ -0,0 +1,49 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Logging
|
3
|
+
def self.initialize_logger(log_target=$stdout, log_level=::Logger::INFO)
|
4
|
+
@counter ||= 0
|
5
|
+
@counter = @counter + 1
|
6
|
+
old_logger = defined?(@logger) ? @logger : nil
|
7
|
+
@logger = Logger.new(log_target)
|
8
|
+
@logger.level = log_level
|
9
|
+
old_logger.close if old_logger and close_old_logger?
|
10
|
+
@logger
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.close_old_logger=(boolean)
|
14
|
+
@close_old_logger = !!boolean
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.close_old_logger?
|
18
|
+
defined?(@close_old_logger) ? @close_old_logger : true
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.logger
|
22
|
+
defined?(@logger) ? @logger : initialize_logger
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.logger=(new_logger)
|
26
|
+
@logger = new_logger
|
27
|
+
end
|
28
|
+
|
29
|
+
def logger
|
30
|
+
::Protobuf::Logging.logger
|
31
|
+
end
|
32
|
+
|
33
|
+
def log_exception(ex)
|
34
|
+
logger.error { ex.message }
|
35
|
+
logger.error { ex.backtrace[0..5].join("\n") }
|
36
|
+
logger.debug { ex.backtrace.join("\n") }
|
37
|
+
end
|
38
|
+
|
39
|
+
def log_signature
|
40
|
+
@_log_signature ||= "[#{self.class == Class ? self.name : self.class.name}]"
|
41
|
+
end
|
42
|
+
|
43
|
+
def sign_message(message)
|
44
|
+
"#{log_signature} #{message}"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Inspired by [mperham](https://github.com/mperham/sidekiq)
|
data/lib/protobuf/rpc/client.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'forwardable'
|
2
2
|
require 'protobuf'
|
3
|
-
require 'protobuf/
|
3
|
+
require 'protobuf/logging'
|
4
4
|
require 'protobuf/rpc/error'
|
5
5
|
require 'protobuf/rpc/connector'
|
6
6
|
|
@@ -8,7 +8,7 @@ module Protobuf
|
|
8
8
|
module Rpc
|
9
9
|
class Client
|
10
10
|
extend Forwardable
|
11
|
-
include Protobuf::
|
11
|
+
include Protobuf::Logging
|
12
12
|
|
13
13
|
def_delegators :@connector, :options, :complete_cb, :success_cb, :failure_cb
|
14
14
|
attr_reader :connector
|
@@ -29,7 +29,7 @@ module Protobuf
|
|
29
29
|
def initialize(options = {})
|
30
30
|
raise "Invalid client configuration. Service must be defined." if options[:service].nil?
|
31
31
|
@connector = Connector.connector_for_client.new(options)
|
32
|
-
|
32
|
+
logger.debug { sign_message("Initialized with options: #{options.inspect}") }
|
33
33
|
end
|
34
34
|
|
35
35
|
def log_signature
|
@@ -106,28 +106,28 @@ module Protobuf
|
|
106
106
|
def method_missing(method_name, *params)
|
107
107
|
service = options[:service]
|
108
108
|
unless service.rpc_method?(method_name)
|
109
|
-
|
109
|
+
logger.error { sign_message("#{service.name}##{method_name.to_s} not rpc method, passing to super") }
|
110
110
|
super(method_name, *params)
|
111
111
|
else
|
112
|
-
|
112
|
+
logger.debug { sign_message("#{service.name}##{method_name.to_s}") }
|
113
113
|
rpc = service.rpcs[method_name.to_sym]
|
114
114
|
|
115
115
|
options[:request_type] = rpc.request_type
|
116
|
-
|
116
|
+
logger.debug { sign_message("Request Type: #{options[:request_type].name}") }
|
117
117
|
|
118
118
|
options[:response_type] = rpc.response_type
|
119
|
-
|
119
|
+
logger.debug { sign_message("Response Type: #{options[:response_type].name}") }
|
120
120
|
|
121
121
|
options[:method] = method_name.to_s
|
122
122
|
options[:request] = params[0].is_a?(Hash) ? options[:request_type].new(params[0]) : params[0]
|
123
|
-
|
123
|
+
logger.debug { sign_message("Request Data: #{options[:request].inspect}") }
|
124
124
|
|
125
125
|
# Call client to setup on_success and on_failure event callbacks
|
126
126
|
if block_given?
|
127
|
-
|
127
|
+
logger.debug { sign_message("client setup callback given, invoking") }
|
128
128
|
yield(self)
|
129
129
|
else
|
130
|
-
|
130
|
+
logger.debug { sign_message("no block given for callbacks") }
|
131
131
|
end
|
132
132
|
|
133
133
|
send_request
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'timeout'
|
2
|
-
require 'protobuf/
|
2
|
+
require 'protobuf/logging'
|
3
3
|
require 'protobuf/rpc/rpc.pb'
|
4
4
|
require 'protobuf/rpc/buffer'
|
5
5
|
require 'protobuf/rpc/error'
|
@@ -23,7 +23,7 @@ module Protobuf
|
|
23
23
|
}
|
24
24
|
|
25
25
|
class Base
|
26
|
-
include Protobuf::
|
26
|
+
include Protobuf::Logging
|
27
27
|
|
28
28
|
attr_reader :options
|
29
29
|
attr_accessor :success_cb, :failure_cb, :complete_cb
|
@@ -19,17 +19,17 @@ module Protobuf
|
|
19
19
|
|
20
20
|
def complete
|
21
21
|
@stats.stop
|
22
|
-
|
23
|
-
|
22
|
+
logger.info { @stats.to_s }
|
23
|
+
logger.debug { sign_message('Response proceessing complete') }
|
24
24
|
@complete_cb.call(self) unless @complete_cb.nil?
|
25
25
|
rescue => e
|
26
|
-
|
26
|
+
logger.error { sign_message('Complete callback error encountered') }
|
27
27
|
log_exception(e)
|
28
28
|
raise
|
29
29
|
end
|
30
30
|
|
31
31
|
def data_callback(data)
|
32
|
-
|
32
|
+
logger.debug { sign_message('Using data_callback') }
|
33
33
|
@used_data_callback = true
|
34
34
|
@data = data
|
35
35
|
end
|
@@ -42,11 +42,11 @@ module Protobuf
|
|
42
42
|
@error = ClientError.new
|
43
43
|
@error.code = Protobuf::Socketrpc::ErrorReason.fetch(code)
|
44
44
|
@error.message = message
|
45
|
-
|
45
|
+
logger.debug { sign_message("Server failed request (invoking on_failure): #{@error.inspect}") }
|
46
46
|
|
47
47
|
@failure_cb.call(@error) unless @failure_cb.nil?
|
48
48
|
rescue => e
|
49
|
-
|
49
|
+
logger.error { sign_message("Failure callback error encountered") }
|
50
50
|
log_exception(e)
|
51
51
|
raise
|
52
52
|
ensure
|
@@ -71,7 +71,7 @@ module Protobuf
|
|
71
71
|
# Close up the connection as we no longer need it
|
72
72
|
close_connection
|
73
73
|
|
74
|
-
|
74
|
+
logger.debug { sign_message("Parsing response from server (connection closed)") }
|
75
75
|
|
76
76
|
# Parse out the raw response
|
77
77
|
@stats.response_size = @response_data.size unless @response_data.nil?
|
@@ -79,13 +79,13 @@ module Protobuf
|
|
79
79
|
|
80
80
|
# Determine success or failure based on parsed data
|
81
81
|
if response_wrapper.has_field?(:error_reason)
|
82
|
-
|
82
|
+
logger.debug { sign_message("Error response parsed") }
|
83
83
|
|
84
84
|
# fail the call if we already know the client is failed
|
85
85
|
# (don't try to parse out the response payload)
|
86
86
|
fail(response_wrapper.error_reason, response_wrapper.error)
|
87
87
|
else
|
88
|
-
|
88
|
+
logger.debug { sign_message("Successful response parsed") }
|
89
89
|
|
90
90
|
# Ensure client_response is an instance
|
91
91
|
parsed = @options[:response_type].decode(response_wrapper.response_proto.to_s)
|
@@ -125,10 +125,10 @@ module Protobuf
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def succeed(response)
|
128
|
-
|
128
|
+
logger.debug { sign_message("Server succeeded request (invoking on_success)") }
|
129
129
|
@success_cb.call(response) unless @success_cb.nil?
|
130
130
|
rescue => e
|
131
|
-
|
131
|
+
logger.error { sign_message("Success callback error encountered") }
|
132
132
|
log_exception(e)
|
133
133
|
fail(:RPC_ERROR, "An exception occurred while calling on_success: #{e.message}")
|
134
134
|
ensure
|
@@ -153,7 +153,7 @@ module Protobuf
|
|
153
153
|
|
154
154
|
def verify_callbacks
|
155
155
|
unless any_callbacks?
|
156
|
-
|
156
|
+
logger.debug { sign_message("No callbacks set, using data_callback") }
|
157
157
|
@success_cb = @failure_cb = self.method(:data_callback)
|
158
158
|
end
|
159
159
|
end
|
@@ -5,7 +5,7 @@ module Protobuf
|
|
5
5
|
module Connectors
|
6
6
|
class Socket < Base
|
7
7
|
include Protobuf::Rpc::Connectors::Common
|
8
|
-
include Protobuf::
|
8
|
+
include Protobuf::Logging
|
9
9
|
|
10
10
|
def send_request
|
11
11
|
timeout_wrap do
|
@@ -24,18 +24,18 @@ module Protobuf
|
|
24
24
|
|
25
25
|
def close_connection
|
26
26
|
@socket.close
|
27
|
-
|
27
|
+
logger.debug { sign_message('Connector closed') }
|
28
28
|
end
|
29
29
|
|
30
30
|
def connect_to_rpc_server
|
31
31
|
@socket = TCPSocket.new(options[:host], options[:port])
|
32
|
-
|
32
|
+
logger.debug { sign_message("Connection established #{options[:host]}:#{options[:port]}") }
|
33
33
|
end
|
34
34
|
|
35
35
|
# Method to determine error state, must be used with Connector api
|
36
36
|
def error?
|
37
37
|
return true if @error
|
38
|
-
|
38
|
+
logger.debug { sign_message("Error state : #{@socket.closed?}") }
|
39
39
|
@socket.closed?
|
40
40
|
end
|
41
41
|
|
@@ -51,7 +51,7 @@ module Protobuf
|
|
51
51
|
end
|
52
52
|
|
53
53
|
def read_response
|
54
|
-
|
54
|
+
logger.debug { sign_message("error? is #{error?}") }
|
55
55
|
return if error?
|
56
56
|
response_buffer = ::Protobuf::Rpc::Buffer.new(:read)
|
57
57
|
response_buffer << read_data
|
@@ -65,7 +65,7 @@ module Protobuf
|
|
65
65
|
request_buffer.set_data(@request_data)
|
66
66
|
@socket.write(request_buffer.write)
|
67
67
|
@socket.flush
|
68
|
-
|
68
|
+
logger.debug { sign_message("write closed") }
|
69
69
|
end
|
70
70
|
end
|
71
71
|
end
|
@@ -12,7 +12,7 @@ module Protobuf
|
|
12
12
|
# Included Modules
|
13
13
|
#
|
14
14
|
include Protobuf::Rpc::Connectors::Common
|
15
|
-
include Protobuf::
|
15
|
+
include Protobuf::Logging
|
16
16
|
|
17
17
|
##
|
18
18
|
# Class Constants
|
@@ -71,9 +71,9 @@ module Protobuf
|
|
71
71
|
if socket # Make sure the context builds the socket
|
72
72
|
socket.setsockopt(::ZMQ::LINGER, 0)
|
73
73
|
|
74
|
-
|
74
|
+
logger.debug { sign_message("Establishing connection: #{server_uri}") }
|
75
75
|
zmq_error_check(socket.connect(server_uri), :socket_connect)
|
76
|
-
|
76
|
+
logger.debug { sign_message("Connection established to #{server_uri}") }
|
77
77
|
|
78
78
|
if first_alive_load_balance?
|
79
79
|
begin
|
@@ -123,6 +123,8 @@ module Protobuf
|
|
123
123
|
def host_alive?(host)
|
124
124
|
return true unless ping_port_enabled?
|
125
125
|
socket = TCPSocket.new(host, ping_port.to_i)
|
126
|
+
socket.setsockopt(::Socket::IPPROTO_TCP, ::Socket::TCP_NODELAY, 1)
|
127
|
+
socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_LINGER, [1,0].pack('ii'))
|
126
128
|
|
127
129
|
true
|
128
130
|
rescue
|
@@ -155,21 +157,21 @@ module Protobuf
|
|
155
157
|
poller = ::ZMQ::Poller.new
|
156
158
|
poller.register_readable(socket)
|
157
159
|
|
158
|
-
|
160
|
+
logger.debug { sign_message("Sending Request (attempt #{attempt}, #{socket})") }
|
159
161
|
zmq_error_check(socket.send_string(@request_data), :socket_send_string)
|
160
|
-
|
162
|
+
logger.debug { sign_message("Waiting #{timeout} seconds for response (attempt #{attempt}, #{socket})") }
|
161
163
|
|
162
164
|
if poller.poll(timeout * 1000) == 1
|
163
165
|
zmq_error_check(socket.recv_string(@response_data = ""), :socket_recv_string)
|
164
|
-
|
166
|
+
logger.debug { sign_message("Response received (attempt #{attempt}, #{socket})") }
|
165
167
|
else
|
166
|
-
|
168
|
+
logger.debug { sign_message("Timed out waiting for response (attempt #{attempt}, #{socket})") }
|
167
169
|
raise RequestTimeout
|
168
170
|
end
|
169
171
|
ensure
|
170
|
-
|
172
|
+
logger.debug { sign_message("Closing Socket") }
|
171
173
|
zmq_error_check(socket.close, :socket_close) if socket
|
172
|
-
|
174
|
+
logger.debug { sign_message("Socket closed") }
|
173
175
|
end
|
174
176
|
|
175
177
|
# The service we're attempting to connect to
|