protobuf 2.7.11-java → 2.8.0.beta1-java

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 (41) hide show
  1. data/README.md +39 -2
  2. data/lib/protobuf.rb +17 -26
  3. data/lib/protobuf/cli.rb +106 -86
  4. data/lib/protobuf/field/float_field.rb +5 -1
  5. data/lib/protobuf/rpc/connectors/base.rb +1 -1
  6. data/lib/protobuf/rpc/connectors/zmq.rb +157 -29
  7. data/lib/protobuf/rpc/dynamic_discovery.pb.rb +49 -0
  8. data/lib/protobuf/rpc/error/client_error.rb +5 -5
  9. data/lib/protobuf/rpc/error/server_error.rb +7 -7
  10. data/lib/protobuf/rpc/rpc.pb.rb +13 -12
  11. data/lib/protobuf/rpc/servers/evented_runner.rb +11 -6
  12. data/lib/protobuf/rpc/servers/socket/server.rb +19 -15
  13. data/lib/protobuf/rpc/servers/socket_runner.rb +21 -18
  14. data/lib/protobuf/rpc/servers/zmq/broker.rb +104 -94
  15. data/lib/protobuf/rpc/servers/zmq/server.rb +263 -43
  16. data/lib/protobuf/rpc/servers/zmq/util.rb +18 -6
  17. data/lib/protobuf/rpc/servers/zmq/worker.rb +102 -39
  18. data/lib/protobuf/rpc/servers/zmq_runner.rb +31 -20
  19. data/lib/protobuf/rpc/service.rb +24 -12
  20. data/lib/protobuf/rpc/service_directory.rb +206 -0
  21. data/lib/protobuf/rpc/stat.rb +1 -1
  22. data/lib/protobuf/version.rb +1 -1
  23. data/proto/dynamic_discovery.proto +44 -0
  24. data/spec/benchmark/tasks.rb +1 -3
  25. data/spec/functional/socket_server_spec.rb +6 -5
  26. data/spec/functional/zmq_server_spec.rb +59 -30
  27. data/spec/lib/protobuf/cli_spec.rb +49 -54
  28. data/spec/lib/protobuf/enum_spec.rb +1 -1
  29. data/spec/lib/protobuf/rpc/client_spec.rb +1 -1
  30. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +43 -1
  31. data/spec/lib/protobuf/rpc/servers/evented_server_spec.rb +2 -1
  32. data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +9 -8
  33. data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +24 -19
  34. data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +5 -5
  35. data/spec/lib/protobuf/rpc/service_directory_spec.rb +183 -0
  36. data/spec/support/server.rb +21 -12
  37. data/spec/support/test/resource.pb.rb +6 -0
  38. data/spec/support/test/resource.proto +5 -0
  39. data/spec/support/test/resource_service.rb +7 -0
  40. metadata +11 -11
  41. data/spec/lib/protobuf/rpc/servers/zmq/broker_spec.rb +0 -31
@@ -1,23 +1,38 @@
1
1
  require 'protobuf/rpc/connectors/base'
2
+ require 'protobuf/rpc/service_directory'
2
3
 
3
4
  module Protobuf
4
5
  module Rpc
5
6
  module Connectors
6
7
  class Zmq < Base
8
+
9
+ ##
10
+ # Included Modules
11
+ #
12
+
7
13
  include Protobuf::Rpc::Connectors::Common
8
14
  include Protobuf::Logger::LogMethods
9
15
 
16
+ ##
17
+ # Class Constants
18
+ #
19
+
20
+ CLIENT_RETRIES = (ENV['PB_CLIENT_RETRIES'] || 3)
21
+
22
+ ##
23
+ # Instance methods
24
+ #
25
+
26
+ # Start the request/response cycle. We implement the Lazy Pirate
27
+ # req/reply reliability pattern as laid out in the ZMQ Guide, Chapter 4.
28
+ #
29
+ # @see http://zguide.zeromq.org/php:chapter4#Client-side-Reliability-Lazy-Pirate-Pattern
30
+ #
10
31
  def send_request
11
- timeout_wrap do
12
- setup_connection
13
- connect_to_rpc_server
14
- post_init
15
- read_response
16
- end
32
+ setup_connection
33
+ poll_send_data
17
34
  ensure
18
- @socket.close if @socket
19
- @zmq_context.terminate if @zmq_context
20
- @zmq_context = nil
35
+ close_connection
21
36
  end
22
37
 
23
38
  def log_signature
@@ -26,45 +41,158 @@ module Protobuf
26
41
 
27
42
  private
28
43
 
44
+ ##
45
+ # Private Instance methods
46
+ #
47
+
29
48
  def close_connection
30
- return if @error
31
- zmq_error_check(@socket.close)
32
- zmq_error_check(@zmq_context.terminate)
33
- log_debug { sign_message("Connector closed") }
49
+ socket_close
50
+ zmq_context_terminate
34
51
  end
35
52
 
53
+ # Establish a request socket connection to the remote rpc_server.
54
+ # Set the socket option LINGER to 0 so that we don't wait
55
+ # for queued messages to be accepted when the socket/context are
56
+ # asked to close/terminate.
57
+ #
36
58
  def connect_to_rpc_server
37
- return if @error
38
- log_debug { sign_message("Establishing connection: #{options[:host]}:#{options[:port]}") }
39
- @zmq_context = ::ZMQ::Context.new
40
- @socket = @zmq_context.socket(::ZMQ::REQ)
41
- zmq_error_check(@socket.connect("tcp://#{options[:host]}:#{options[:port]}"))
42
- log_debug { sign_message("Connection established #{options[:host]}:#{options[:port]}") }
59
+ return if error?
60
+
61
+ server_uri = lookup_server_uri
62
+ log_debug { sign_message("Establishing connection: #{server_uri}") }
63
+ socket.setsockopt(::ZMQ::LINGER, 0)
64
+ zmq_error_check(socket.connect(server_uri), :socket_connect)
65
+ zmq_error_check(poller.register_readable(socket), :poller_register_readable)
66
+ log_debug { sign_message("Connection established to #{server_uri}") }
43
67
  end
44
68
 
45
- # Method to determine error state, must be used with Connector api
69
+ # Method to determine error state, must be used with Connector API.
70
+ #
46
71
  def error?
47
- !!@error
72
+ !! @error
73
+ end
74
+
75
+ # Lookup a server uri for the requested service in the service
76
+ # directory. If the service directory is not running, default
77
+ # to the host and port in the options
78
+ #
79
+ def lookup_server_uri
80
+ if service_directory.running?
81
+ listing = service_directory.lookup(service)
82
+ host, port = listing.address, listing.port if listing
83
+ end
84
+
85
+ host, port = options[:host], options[:port] unless host && port
86
+
87
+ "tcp://#{host}:#{port}"
88
+ end
89
+
90
+ # Trying a number of times, attempt to get a response from the server.
91
+ # If we haven't received a legitimate response in the CLIENT_RETRIES number
92
+ # of retries, fail the request.
93
+ #
94
+ def poll_send_data
95
+ return if error?
96
+
97
+ poll_timeout = (options[:timeout].to_f / CLIENT_RETRIES.to_f) * 1000
98
+
99
+ CLIENT_RETRIES.times do |n|
100
+ connect_to_rpc_server
101
+ log_debug { sign_message("Sending Request (attempt #{n + 1}, #{socket})") }
102
+ send_data
103
+ log_debug { sign_message("Request sending complete (attempt #{n + 1}, #{socket})") }
104
+
105
+ if poller.poll(poll_timeout) == 1
106
+ read_response
107
+ return
108
+ else
109
+ close_connection
110
+ end
111
+ end
112
+
113
+ fail(:RPC_FAILED, "The server took longer than #{options[:timeout]} seconds to respond")
48
114
  end
49
115
 
116
+ def poller
117
+ @poller ||= ::ZMQ::Poller.new
118
+ end
119
+
120
+ # Read the string response from the available readable. This will be
121
+ # the current @socket. Calls `parse_response` to invoke the success or
122
+ # failed callbacks, depending on the state of the communication
123
+ # and response data.
124
+ #
50
125
  def read_response
51
- return if @error
126
+ return if error?
127
+
52
128
  @response_data = ''
53
- zmq_error_check(@socket.recv_string(@response_data))
129
+ zmq_error_check(socket.recv_string(@response_data), :socket_recv_string)
130
+
54
131
  parse_response
55
132
  end
56
133
 
134
+ # Send the request data to the remote rpc_server.
135
+ #
57
136
  def send_data
58
- return if @error
59
- log_debug { sign_message("Sending Request: #{@request_data}") }
137
+ return if error?
138
+
60
139
  @stats.request_size = @request_data.size
61
- zmq_error_check(@socket.send_string(@request_data))
62
- log_debug { sign_message("write closed") }
140
+ zmq_error_check(socket.send_string(@request_data), :socket_send_string)
141
+ end
142
+
143
+ # The service we're attempting to connect to
144
+ #
145
+ def service
146
+ options[:service]
147
+ end
148
+
149
+ # Alias for ::Protobuf::Rpc::ServiceDirectory.instance
150
+ def service_directory
151
+ ::Protobuf::Rpc::ServiceDirectory.instance
152
+ end
153
+
154
+ # Setup a ZMQ request socket in the current zmq context.
155
+ #
156
+ def socket
157
+ @socket ||= zmq_context.socket(::ZMQ::REQ)
63
158
  end
64
159
 
65
- def zmq_error_check(return_code)
66
- raise "Last API call failed at #{caller(1)}" unless return_code >= 0
160
+ def socket_close
161
+ if socket
162
+ log_debug { sign_message("Closing Socket") }
163
+ zmq_error_check(socket.close, :socket_close)
164
+ log_debug { sign_message("Socket closed") }
165
+ @socket = nil
166
+ end
167
+ end
168
+
169
+ # Return the ZMQ Context to use for this process.
170
+ # If the context does not exist, create it, then register
171
+ # an exit block to ensure the context is terminated correctly.
172
+ #
173
+ def zmq_context
174
+ @zmq_context ||= ::ZMQ::Context.new
175
+ end
176
+
177
+ # Terminate the zmq_context (if any).
178
+ #
179
+ def zmq_context_terminate
180
+ log_debug { sign_message("Terminating ZMQ Context") }
181
+ @zmq_context.try(:terminate)
182
+ @zmq_context = nil
183
+ log_debug { sign_message("ZMQ Context terminated") }
67
184
  end
185
+
186
+ def zmq_error_check(return_code, source)
187
+ unless ::ZMQ::Util.resultcode_ok?(return_code || -1)
188
+ raise <<-ERROR
189
+ Last ZMQ API call to #{source} failed with "#{::ZMQ::Util.error_string}".
190
+
191
+ #{caller(1).join($/)}
192
+ ERROR
193
+ end
194
+ end
195
+
68
196
  end
69
197
  end
70
198
  end
@@ -0,0 +1,49 @@
1
+ ##
2
+ # This file is auto-generated. DO NOT EDIT!
3
+ #
4
+ require 'protobuf/message'
5
+
6
+ module Protobuf
7
+
8
+ module Rpc
9
+
10
+ module DynamicDiscovery
11
+
12
+ ##
13
+ # Enum Classes
14
+ #
15
+ class BeaconType < ::Protobuf::Enum
16
+ define :HEARTBEAT, 0
17
+ define :FLATLINE, 1
18
+ end
19
+
20
+
21
+ ##
22
+ # Message Classes
23
+ #
24
+ class Server < ::Protobuf::Message; end
25
+ class Beacon < ::Protobuf::Message; end
26
+
27
+ ##
28
+ # Message Fields
29
+ #
30
+ class Server
31
+ optional ::Protobuf::Field::StringField, :uuid, 1
32
+ optional ::Protobuf::Field::StringField, :address, 2
33
+ optional ::Protobuf::Field::StringField, :port, 3
34
+ optional ::Protobuf::Field::Int32Field, :ttl, 4
35
+ repeated ::Protobuf::Field::StringField, :services, 5
36
+ end
37
+
38
+ class Beacon
39
+ optional ::Protobuf::Rpc::DynamicDiscovery::BeaconType, :beacon_type, 1
40
+ optional ::Protobuf::Rpc::DynamicDiscovery::Server, :server, 2
41
+ end
42
+
43
+
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
@@ -2,30 +2,30 @@ require 'protobuf/rpc/error'
2
2
 
3
3
  module Protobuf
4
4
  module Rpc
5
-
5
+
6
6
  class InvalidRequestProto < PbError
7
7
  def initialize(message='Invalid request type given')
8
8
  super message, 'INVALID_REQUEST_PROTO'
9
9
  end
10
10
  end
11
-
11
+
12
12
  class BadResponseProto < PbError
13
13
  def initialize(message='Bad response type from server')
14
14
  super message, 'BAD_RESPONSE_PROTO'
15
15
  end
16
16
  end
17
-
17
+
18
18
  class UnkownHost < PbError
19
19
  def initialize(message='Unknown host or port')
20
20
  super message, 'UNKNOWN_HOST'
21
21
  end
22
22
  end
23
-
23
+
24
24
  class IOError < PbError
25
25
  def initialize(message='IO Error occurred')
26
26
  super message, 'IO_ERROR'
27
27
  end
28
28
  end
29
-
29
+
30
30
  end
31
31
  end
@@ -2,42 +2,42 @@ require 'protobuf/rpc/rpc.pb'
2
2
 
3
3
  module Protobuf
4
4
  module Rpc
5
-
5
+
6
6
  class BadRequestData < PbError
7
7
  def initialize message='Unable to parse request'
8
8
  super message, 'BAD_REQUEST_DATA'
9
9
  end
10
10
  end
11
-
11
+
12
12
  class BadRequestProto < PbError
13
13
  def initialize message='Request is of wrong type'
14
14
  super message, 'BAD_REQUEST_PROTO'
15
15
  end
16
16
  end
17
-
17
+
18
18
  class ServiceNotFound < PbError
19
19
  def initialize message='Service class not found'
20
20
  super message, 'SERVICE_NOT_FOUND'
21
21
  end
22
22
  end
23
-
23
+
24
24
  class MethodNotFound < PbError
25
25
  def initialize message='Service method not found'
26
26
  super message, 'METHOD_NOT_FOUND'
27
27
  end
28
28
  end
29
-
29
+
30
30
  class RpcError < PbError
31
31
  def initialize message='RPC exception occurred'
32
32
  super message, 'RPC_ERROR'
33
33
  end
34
34
  end
35
-
35
+
36
36
  class RpcFailed < PbError
37
37
  def initialize message='RPC failed'
38
38
  super message, 'RPC_FAILED'
39
39
  end
40
40
  end
41
-
41
+
42
42
  end
43
43
  end
@@ -4,22 +4,13 @@
4
4
  require 'protobuf/message'
5
5
 
6
6
  module Protobuf
7
+
7
8
  module Socketrpc
9
+
8
10
  ##
9
11
  # Enum Classes
10
12
  #
11
- class ErrorReason < ::Protobuf::Enum; end
12
-
13
- ##
14
- # Message Classes
15
- #
16
- class Request < ::Protobuf::Message; end
17
- class Response < ::Protobuf::Message; end
18
-
19
- ##
20
- # Enum Values
21
- #
22
- class ErrorReason
13
+ class ErrorReason < ::Protobuf::Enum
23
14
  define :BAD_REQUEST_DATA, 0
24
15
  define :BAD_REQUEST_PROTO, 1
25
16
  define :SERVICE_NOT_FOUND, 2
@@ -32,6 +23,13 @@ module Protobuf
32
23
  define :IO_ERROR, 9
33
24
  end
34
25
 
26
+
27
+ ##
28
+ # Message Classes
29
+ #
30
+ class Request < ::Protobuf::Message; end
31
+ class Response < ::Protobuf::Message; end
32
+
35
33
  ##
36
34
  # Message Fields
37
35
  #
@@ -49,5 +47,8 @@ module Protobuf
49
47
  optional ::Protobuf::Socketrpc::ErrorReason, :error_reason, 4
50
48
  end
51
49
 
50
+
52
51
  end
52
+
53
53
  end
54
+
@@ -2,22 +2,27 @@ module Protobuf
2
2
  module Rpc
3
3
  class EventedRunner
4
4
 
5
- def self.register_signals
6
- # Noop
5
+ def initialize(options)
6
+ @options = options
7
7
  end
8
8
 
9
- def self.run(options)
9
+ def run
10
10
  # Startup and run the rpc server
11
11
  ::EventMachine.schedule do
12
- ::EventMachine.start_server(options[:host], options[:port], ::Protobuf::Rpc::Evented::Server)
12
+ ::EventMachine.start_server(
13
+ @options[:host],
14
+ @options[:port],
15
+ ::Protobuf::Rpc::Evented::Server
16
+ )
13
17
  end
14
18
 
15
19
  # Join or start the reactor
16
- yield if block_given?
20
+ yield if block_given?
21
+
17
22
  ::EM.reactor_running? ? ::EM.reactor_thread.join : ::EM.run
18
23
  end
19
24
 
20
- def self.stop
25
+ def stop
21
26
  ::EventMachine.stop_event_loop if ::EventMachine.reactor_running?
22
27
  end
23
28
 
@@ -11,12 +11,16 @@ module Protobuf
11
11
 
12
12
  AUTO_COLLECT_TIMEOUT = 5 # seconds
13
13
 
14
- def self.cleanup?
14
+ def initialize(options)
15
+ @options = options
16
+ end
17
+
18
+ def cleanup?
15
19
  # every 10 connections run a cleanup routine after closing the response
16
20
  @threads.size > (@threshold - 1) && (@threads.size % @threshold) == 0
17
21
  end
18
22
 
19
- def self.cleanup_threads
23
+ def cleanup_threads
20
24
  log_debug { sign_message("Thread cleanup - #{@threads.size} - start") }
21
25
 
22
26
  @threads = @threads.select do |t|
@@ -32,11 +36,11 @@ module Protobuf
32
36
  log_debug { sign_message("Thread cleanup - #{@threads.size} - complete") }
33
37
  end
34
38
 
35
- def self.log_signature
39
+ def log_signature
36
40
  @_log_signature ||= "server-#{self.class.name}"
37
41
  end
38
42
 
39
- def self.new_worker(socket)
43
+ def new_worker(socket)
40
44
  Thread.new(socket) do |sock|
41
45
  ::Protobuf::Rpc::Socket::Worker.new(sock) do |s|
42
46
  s.close
@@ -44,12 +48,12 @@ module Protobuf
44
48
  end
45
49
  end
46
50
 
47
- def self.run(options = {})
51
+ def run
48
52
  log_debug { sign_message("Run") }
49
- host = options[:host]
50
- port = options[:port]
51
- backlog = options[:backlog]
52
- @threshold = options[:threshold]
53
+ host = @options[:host]
54
+ port = @options[:port]
55
+ backlog = @options[:backlog]
56
+ @threshold = @options[:threshold]
53
57
 
54
58
  @threads = []
55
59
  @server = ::TCPServer.new(host, port)
@@ -62,8 +66,9 @@ module Protobuf
62
66
 
63
67
  while running?
64
68
  log_debug { sign_message("Waiting for connections") }
69
+ ready_cnxns = IO.select(@listen_fds, [], [], AUTO_COLLECT_TIMEOUT) rescue nil
65
70
 
66
- if ready_cnxns = IO.select(@listen_fds, [], [], AUTO_COLLECT_TIMEOUT)
71
+ if ready_cnxns
67
72
  cnxns = ready_cnxns.first
68
73
  cnxns.each do |client|
69
74
  case
@@ -96,16 +101,15 @@ module Protobuf
96
101
  raise #if running?
97
102
  end
98
103
 
99
- def self.running?
100
- @running
104
+ def running?
105
+ !!@running
101
106
  end
102
107
 
103
- def self.stop
108
+ def stop
104
109
  @running = false
105
- @server.close if @server
110
+ @server.try(:close)
106
111
  end
107
112
  end
108
-
109
113
  end
110
114
  end
111
115
  end