prepor-protobuf 3.5.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.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.rubocop.yml +51 -0
- data/.rubocop_todo.yml +89 -0
- data/.travis.yml +25 -0
- data/.yardopts +5 -0
- data/CHANGES.md +256 -0
- data/CONTRIBUTING.md +16 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +33 -0
- data/Rakefile +64 -0
- data/bin/protoc-gen-ruby +16 -0
- data/bin/rpc_server +5 -0
- data/install-protobuf.sh +28 -0
- data/lib/protobuf.rb +100 -0
- data/lib/protobuf/cli.rb +242 -0
- data/lib/protobuf/code_generator.rb +44 -0
- data/lib/protobuf/decoder.rb +73 -0
- data/lib/protobuf/deprecation.rb +112 -0
- data/lib/protobuf/descriptors.rb +3 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +48 -0
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +251 -0
- data/lib/protobuf/encoder.rb +67 -0
- data/lib/protobuf/enum.rb +303 -0
- data/lib/protobuf/exceptions.rb +9 -0
- data/lib/protobuf/field.rb +74 -0
- data/lib/protobuf/field/base_field.rb +267 -0
- data/lib/protobuf/field/bool_field.rb +59 -0
- data/lib/protobuf/field/bytes_field.rb +82 -0
- data/lib/protobuf/field/double_field.rb +25 -0
- data/lib/protobuf/field/enum_field.rb +68 -0
- data/lib/protobuf/field/field_array.rb +87 -0
- data/lib/protobuf/field/fixed32_field.rb +25 -0
- data/lib/protobuf/field/fixed64_field.rb +28 -0
- data/lib/protobuf/field/float_field.rb +41 -0
- data/lib/protobuf/field/int32_field.rb +21 -0
- data/lib/protobuf/field/int64_field.rb +21 -0
- data/lib/protobuf/field/integer_field.rb +23 -0
- data/lib/protobuf/field/message_field.rb +65 -0
- data/lib/protobuf/field/sfixed32_field.rb +27 -0
- data/lib/protobuf/field/sfixed64_field.rb +28 -0
- data/lib/protobuf/field/signed_integer_field.rb +29 -0
- data/lib/protobuf/field/sint32_field.rb +21 -0
- data/lib/protobuf/field/sint64_field.rb +21 -0
- data/lib/protobuf/field/string_field.rb +34 -0
- data/lib/protobuf/field/uint32_field.rb +21 -0
- data/lib/protobuf/field/uint64_field.rb +21 -0
- data/lib/protobuf/field/varint_field.rb +73 -0
- data/lib/protobuf/generators/base.rb +70 -0
- data/lib/protobuf/generators/enum_generator.rb +41 -0
- data/lib/protobuf/generators/extension_generator.rb +27 -0
- data/lib/protobuf/generators/field_generator.rb +131 -0
- data/lib/protobuf/generators/file_generator.rb +135 -0
- data/lib/protobuf/generators/group_generator.rb +112 -0
- data/lib/protobuf/generators/message_generator.rb +98 -0
- data/lib/protobuf/generators/printable.rb +160 -0
- data/lib/protobuf/generators/service_generator.rb +26 -0
- data/lib/protobuf/lifecycle.rb +33 -0
- data/lib/protobuf/logging.rb +39 -0
- data/lib/protobuf/message.rb +193 -0
- data/lib/protobuf/message/fields.rb +133 -0
- data/lib/protobuf/message/serialization.rb +89 -0
- data/lib/protobuf/optionable.rb +23 -0
- data/lib/protobuf/rpc/buffer.rb +77 -0
- data/lib/protobuf/rpc/client.rb +168 -0
- data/lib/protobuf/rpc/connector.rb +19 -0
- data/lib/protobuf/rpc/connectors/base.rb +55 -0
- data/lib/protobuf/rpc/connectors/common.rb +176 -0
- data/lib/protobuf/rpc/connectors/socket.rb +73 -0
- data/lib/protobuf/rpc/connectors/zmq.rb +322 -0
- data/lib/protobuf/rpc/dynamic_discovery.pb.rb +49 -0
- data/lib/protobuf/rpc/env.rb +58 -0
- data/lib/protobuf/rpc/error.rb +28 -0
- data/lib/protobuf/rpc/error/client_error.rb +31 -0
- data/lib/protobuf/rpc/error/server_error.rb +43 -0
- data/lib/protobuf/rpc/middleware.rb +25 -0
- 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/rpc.pb.rb +55 -0
- data/lib/protobuf/rpc/server.rb +39 -0
- data/lib/protobuf/rpc/servers/socket/server.rb +123 -0
- data/lib/protobuf/rpc/servers/socket/worker.rb +56 -0
- data/lib/protobuf/rpc/servers/socket_runner.rb +40 -0
- data/lib/protobuf/rpc/servers/zmq/broker.rb +193 -0
- data/lib/protobuf/rpc/servers/zmq/server.rb +320 -0
- data/lib/protobuf/rpc/servers/zmq/util.rb +48 -0
- data/lib/protobuf/rpc/servers/zmq/worker.rb +104 -0
- data/lib/protobuf/rpc/servers/zmq_runner.rb +62 -0
- data/lib/protobuf/rpc/service.rb +179 -0
- data/lib/protobuf/rpc/service_directory.rb +253 -0
- data/lib/protobuf/rpc/service_dispatcher.rb +46 -0
- data/lib/protobuf/rpc/service_filters.rb +272 -0
- data/lib/protobuf/rpc/stat.rb +97 -0
- data/lib/protobuf/socket.rb +21 -0
- data/lib/protobuf/tasks.rb +1 -0
- data/lib/protobuf/tasks/compile.rake +61 -0
- data/lib/protobuf/version.rb +3 -0
- data/lib/protobuf/wire_type.rb +10 -0
- data/lib/protobuf/zmq.rb +21 -0
- data/proto/dynamic_discovery.proto +44 -0
- data/proto/google/protobuf/compiler/plugin.proto +147 -0
- data/proto/google/protobuf/descriptor.proto +620 -0
- data/proto/rpc.proto +62 -0
- data/protobuf.gemspec +51 -0
- data/spec/benchmark/tasks.rb +139 -0
- data/spec/bin/protoc-gen-ruby_spec.rb +23 -0
- data/spec/data/data.bin +3 -0
- data/spec/data/types.bin +0 -0
- data/spec/encoding/all_types_spec.rb +105 -0
- data/spec/encoding/extreme_values_spec.rb +0 -0
- data/spec/functional/class_inheritance_spec.rb +52 -0
- data/spec/functional/socket_server_spec.rb +59 -0
- data/spec/functional/zmq_server_spec.rb +105 -0
- data/spec/lib/protobuf/cli_spec.rb +273 -0
- data/spec/lib/protobuf/code_generator_spec.rb +60 -0
- data/spec/lib/protobuf/enum_spec.rb +265 -0
- data/spec/lib/protobuf/field/bool_field_spec.rb +51 -0
- data/spec/lib/protobuf/field/field_array_spec.rb +69 -0
- data/spec/lib/protobuf/field/float_field_spec.rb +55 -0
- data/spec/lib/protobuf/field/int32_field_spec.rb +89 -0
- data/spec/lib/protobuf/field/string_field_spec.rb +45 -0
- data/spec/lib/protobuf/field_spec.rb +191 -0
- data/spec/lib/protobuf/generators/base_spec.rb +84 -0
- data/spec/lib/protobuf/generators/enum_generator_spec.rb +73 -0
- data/spec/lib/protobuf/generators/extension_generator_spec.rb +42 -0
- data/spec/lib/protobuf/generators/field_generator_spec.rb +102 -0
- data/spec/lib/protobuf/generators/file_generator_spec.rb +32 -0
- data/spec/lib/protobuf/generators/message_generator_spec.rb +0 -0
- data/spec/lib/protobuf/generators/service_generator_spec.rb +46 -0
- data/spec/lib/protobuf/lifecycle_spec.rb +94 -0
- data/spec/lib/protobuf/message_spec.rb +526 -0
- data/spec/lib/protobuf/optionable_spec.rb +46 -0
- data/spec/lib/protobuf/rpc/client_spec.rb +66 -0
- data/spec/lib/protobuf/rpc/connector_spec.rb +26 -0
- data/spec/lib/protobuf/rpc/connectors/base_spec.rb +50 -0
- data/spec/lib/protobuf/rpc/connectors/common_spec.rb +170 -0
- data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +36 -0
- data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +117 -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 +38 -0
- data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +43 -0
- data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +55 -0
- data/spec/lib/protobuf/rpc/servers/zmq/worker_spec.rb +35 -0
- data/spec/lib/protobuf/rpc/service_directory_spec.rb +293 -0
- data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +52 -0
- data/spec/lib/protobuf/rpc/service_filters_spec.rb +517 -0
- data/spec/lib/protobuf/rpc/service_spec.rb +162 -0
- data/spec/lib/protobuf/rpc/stat_spec.rb +68 -0
- data/spec/lib/protobuf_spec.rb +98 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/support/all.rb +6 -0
- data/spec/support/packed_field.rb +22 -0
- data/spec/support/server.rb +64 -0
- data/spec/support/test/all_types.data.bin +0 -0
- data/spec/support/test/all_types.data.txt +119 -0
- data/spec/support/test/defaults.pb.rb +27 -0
- data/spec/support/test/defaults.proto +9 -0
- data/spec/support/test/enum.pb.rb +55 -0
- data/spec/support/test/enum.proto +34 -0
- data/spec/support/test/extended.pb.rb +18 -0
- data/spec/support/test/extended.proto +10 -0
- data/spec/support/test/extreme_values.data.bin +0 -0
- data/spec/support/test/google_unittest.pb.rb +537 -0
- data/spec/support/test/google_unittest.proto +713 -0
- data/spec/support/test/google_unittest_import.pb.rb +39 -0
- data/spec/support/test/google_unittest_import.proto +64 -0
- data/spec/support/test/google_unittest_import_public.pb.rb +10 -0
- data/spec/support/test/google_unittest_import_public.proto +38 -0
- data/spec/support/test/multi_field_extensions.pb.rb +58 -0
- data/spec/support/test/multi_field_extensions.proto +33 -0
- data/spec/support/test/resource.pb.rb +119 -0
- data/spec/support/test/resource.proto +94 -0
- data/spec/support/test/resource_service.rb +23 -0
- data/spec/support/test_app_file.rb +2 -0
- metadata +502 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
require 'protobuf'
|
|
2
|
+
require 'protobuf/logging'
|
|
3
|
+
require 'protobuf/rpc/rpc.pb'
|
|
4
|
+
require 'protobuf/rpc/buffer'
|
|
5
|
+
require 'protobuf/rpc/env'
|
|
6
|
+
require 'protobuf/rpc/error'
|
|
7
|
+
require 'protobuf/rpc/middleware'
|
|
8
|
+
require 'protobuf/rpc/service_dispatcher'
|
|
9
|
+
|
|
10
|
+
module Protobuf
|
|
11
|
+
module Rpc
|
|
12
|
+
module Server
|
|
13
|
+
def gc_pause
|
|
14
|
+
::GC.disable if ::Protobuf.gc_pause_server_request?
|
|
15
|
+
|
|
16
|
+
yield
|
|
17
|
+
|
|
18
|
+
::GC.enable if ::Protobuf.gc_pause_server_request?
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Invoke the service method dictated by the proto wrapper request object
|
|
22
|
+
#
|
|
23
|
+
def handle_request(request_data)
|
|
24
|
+
# Create an env object that holds different parts of the environment and
|
|
25
|
+
# is available to all of the middlewares
|
|
26
|
+
env = Env.new('encoded_request' => request_data, 'log_signature' => log_signature)
|
|
27
|
+
|
|
28
|
+
# Invoke the middleware stack, the last of which is the service dispatcher
|
|
29
|
+
env = Rpc.middleware.call(env)
|
|
30
|
+
|
|
31
|
+
env.encoded_response
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def log_signature
|
|
35
|
+
@_log_signature ||= "[server-#{self.class.name}]"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
require 'set'
|
|
2
|
+
|
|
3
|
+
require 'protobuf/rpc/servers/socket/worker'
|
|
4
|
+
|
|
5
|
+
module Protobuf
|
|
6
|
+
module Rpc
|
|
7
|
+
module Socket
|
|
8
|
+
class Server
|
|
9
|
+
include ::Protobuf::Logging
|
|
10
|
+
|
|
11
|
+
AUTO_COLLECT_TIMEOUT = 5 # seconds
|
|
12
|
+
|
|
13
|
+
private
|
|
14
|
+
|
|
15
|
+
attr_accessor :threshold, :host, :port, :backlog
|
|
16
|
+
attr_writer :running
|
|
17
|
+
|
|
18
|
+
public
|
|
19
|
+
|
|
20
|
+
attr_reader :running
|
|
21
|
+
alias_method :running?, :running
|
|
22
|
+
|
|
23
|
+
def initialize(options)
|
|
24
|
+
self.running = false
|
|
25
|
+
self.host = options.fetch(:host)
|
|
26
|
+
self.port = options.fetch(:port)
|
|
27
|
+
self.backlog = options.fetch(:backlog, 100)
|
|
28
|
+
self.threshold = options.fetch(:threshold, 100)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def threads
|
|
32
|
+
@threads ||= []
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def working
|
|
36
|
+
@working ||= Set.new
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def cleanup?
|
|
40
|
+
# every `threshold` connections run a cleanup routine after closing the response
|
|
41
|
+
threads.size > 0 && threads.size % threshold == 0
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def cleanup_threads
|
|
45
|
+
logger.debug { sign_message("Thread cleanup - #{threads.size} - start") }
|
|
46
|
+
|
|
47
|
+
threads.delete_if do |hash|
|
|
48
|
+
unless (thread = hash.fetch(:thread)).alive?
|
|
49
|
+
thread.join
|
|
50
|
+
working.delete(hash.fetch(:socket))
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
logger.debug { sign_message("Thread cleanup - #{threads.size} - complete") }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def log_signature
|
|
58
|
+
@_log_signature ||= "[server-#{self.class.name}]"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def new_worker(socket)
|
|
62
|
+
Thread.new(socket) do |sock|
|
|
63
|
+
::Protobuf::Rpc::Socket::Worker.new(sock) do |s|
|
|
64
|
+
s.close
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def run
|
|
70
|
+
logger.debug { sign_message("Run") }
|
|
71
|
+
|
|
72
|
+
server = ::TCPServer.new(host, port)
|
|
73
|
+
fail "The server was unable to start properly." if server.closed?
|
|
74
|
+
|
|
75
|
+
begin
|
|
76
|
+
server.listen(backlog)
|
|
77
|
+
listen_fds = [server]
|
|
78
|
+
self.running = true
|
|
79
|
+
|
|
80
|
+
while running?
|
|
81
|
+
logger.debug { sign_message("Waiting for connections") }
|
|
82
|
+
ready_cnxns = begin
|
|
83
|
+
IO.select(listen_fds, [], [], AUTO_COLLECT_TIMEOUT)
|
|
84
|
+
rescue IOError
|
|
85
|
+
nil
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
if ready_cnxns
|
|
89
|
+
ready_cnxns.first.each do |client|
|
|
90
|
+
case
|
|
91
|
+
when !running?
|
|
92
|
+
# no-op
|
|
93
|
+
when client == server
|
|
94
|
+
logger.debug { sign_message("Accepted new connection") }
|
|
95
|
+
client, _sockaddr = server.accept
|
|
96
|
+
listen_fds << client
|
|
97
|
+
else
|
|
98
|
+
unless working.include?(client)
|
|
99
|
+
working << listen_fds.delete(client)
|
|
100
|
+
logger.debug { sign_message("Working") }
|
|
101
|
+
threads << { :thread => new_worker(client), :socket => client }
|
|
102
|
+
|
|
103
|
+
cleanup_threads if cleanup?
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
else
|
|
108
|
+
# Run a cleanup if select times out while waiting
|
|
109
|
+
cleanup_threads if threads.size > 1
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
ensure
|
|
113
|
+
server.close
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def stop
|
|
118
|
+
self.running = false
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
require 'protobuf/rpc/server'
|
|
2
|
+
require 'protobuf/logging'
|
|
3
|
+
|
|
4
|
+
module Protobuf
|
|
5
|
+
module Rpc
|
|
6
|
+
module Socket
|
|
7
|
+
class Worker
|
|
8
|
+
include ::Protobuf::Rpc::Server
|
|
9
|
+
include ::Protobuf::Logging
|
|
10
|
+
|
|
11
|
+
def initialize(sock, &complete_cb)
|
|
12
|
+
@socket = sock
|
|
13
|
+
@complete_cb = complete_cb
|
|
14
|
+
|
|
15
|
+
data = read_data
|
|
16
|
+
return unless data
|
|
17
|
+
|
|
18
|
+
gc_pause do
|
|
19
|
+
encoded_response = handle_request(data)
|
|
20
|
+
send_data(encoded_response)
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def read_data
|
|
25
|
+
size_io = StringIO.new
|
|
26
|
+
|
|
27
|
+
until (size_reader = @socket.getc) == "-"
|
|
28
|
+
size_io << size_reader
|
|
29
|
+
end
|
|
30
|
+
str_size_io = size_io.string
|
|
31
|
+
|
|
32
|
+
@socket.read(str_size_io.to_i)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def send_data(data)
|
|
36
|
+
fail 'Socket closed unexpectedly' unless socket_writable?
|
|
37
|
+
response_buffer = Protobuf::Rpc::Buffer.new(:write)
|
|
38
|
+
response_buffer.set_data(data)
|
|
39
|
+
|
|
40
|
+
@socket.write(response_buffer.write)
|
|
41
|
+
@socket.flush
|
|
42
|
+
|
|
43
|
+
@complete_cb.call(@socket)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def log_signature
|
|
47
|
+
@_log_signature ||= "[server-#{self.class}-#{object_id}]"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def socket_writable?
|
|
51
|
+
! @socket.nil? && ! @socket.closed?
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
module Protobuf
|
|
2
|
+
module Rpc
|
|
3
|
+
class SocketRunner
|
|
4
|
+
|
|
5
|
+
private
|
|
6
|
+
|
|
7
|
+
attr_accessor :server
|
|
8
|
+
|
|
9
|
+
public
|
|
10
|
+
|
|
11
|
+
def initialize(options)
|
|
12
|
+
options = case
|
|
13
|
+
when options.is_a?(OpenStruct) then
|
|
14
|
+
options.marshal_dump
|
|
15
|
+
when options.is_a?(Hash) then
|
|
16
|
+
options
|
|
17
|
+
when options.respond_to?(:to_hash) then
|
|
18
|
+
options.to_hash
|
|
19
|
+
else
|
|
20
|
+
fail "Cannot parser Socket Server - server options"
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
self.server = ::Protobuf::Rpc::Socket::Server.new(options)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def run
|
|
27
|
+
yield if block_given?
|
|
28
|
+
server.run
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def running?
|
|
32
|
+
server.running?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def stop
|
|
36
|
+
server.stop
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
require 'thread'
|
|
2
|
+
|
|
3
|
+
module Protobuf
|
|
4
|
+
module Rpc
|
|
5
|
+
module Zmq
|
|
6
|
+
class Broker
|
|
7
|
+
include ::Protobuf::Rpc::Zmq::Util
|
|
8
|
+
|
|
9
|
+
attr_reader :local_queue
|
|
10
|
+
|
|
11
|
+
def initialize(server)
|
|
12
|
+
@server = server
|
|
13
|
+
|
|
14
|
+
init_zmq_context
|
|
15
|
+
init_local_queue
|
|
16
|
+
init_backend_socket
|
|
17
|
+
init_frontend_socket
|
|
18
|
+
init_poller
|
|
19
|
+
rescue
|
|
20
|
+
teardown
|
|
21
|
+
raise
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def run
|
|
25
|
+
@idle_workers = []
|
|
26
|
+
@running = true
|
|
27
|
+
|
|
28
|
+
loop do
|
|
29
|
+
process_local_queue
|
|
30
|
+
rc = @poller.poll(broker_polling_milliseconds)
|
|
31
|
+
|
|
32
|
+
# The server was shutdown and no requests are pending
|
|
33
|
+
break if rc == 0 && !running? && @server.workers.empty?
|
|
34
|
+
# Something went wrong
|
|
35
|
+
break if rc == -1
|
|
36
|
+
|
|
37
|
+
check_and_process_backend
|
|
38
|
+
process_local_queue # Fair ordering so queued requests get in before new requests
|
|
39
|
+
check_and_process_frontend
|
|
40
|
+
end
|
|
41
|
+
ensure
|
|
42
|
+
teardown
|
|
43
|
+
@running = false
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def running?
|
|
47
|
+
@running && @server.running?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def backend_poll_weight
|
|
53
|
+
@backend_poll_weight ||= [ENV["PB_ZMQ_SERVER_BACKEND_POLL_WEIGHT"].to_i, 1].max
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def broker_polling_milliseconds
|
|
57
|
+
@broker_polling_milliseconds ||= [ENV["PB_ZMQ_BROKER_POLLING_MILLISECONDS"].to_i, 500].max
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def check_and_process_backend
|
|
61
|
+
readables_include_backend = @poller.readables.include?(@backend_socket)
|
|
62
|
+
message_count_read_from_backend = 0
|
|
63
|
+
|
|
64
|
+
while readables_include_backend && message_count_read_from_backend < backend_poll_weight
|
|
65
|
+
message_count_read_from_backend += 1
|
|
66
|
+
process_backend
|
|
67
|
+
@poller.poll_nonblock
|
|
68
|
+
readables_include_backend = @poller.readables.include?(@backend_socket)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def check_and_process_frontend
|
|
73
|
+
readables_include_frontend = @poller.readables.include?(@frontend_socket)
|
|
74
|
+
message_count_read_from_frontend = 0
|
|
75
|
+
|
|
76
|
+
while readables_include_frontend && message_count_read_from_frontend < frontend_poll_weight
|
|
77
|
+
message_count_read_from_frontend += 1
|
|
78
|
+
process_frontend
|
|
79
|
+
break unless local_queue_available? # no need to read frontend just to throw away messages, will prioritize backend when full
|
|
80
|
+
@poller.poll_nonblock
|
|
81
|
+
readables_include_frontend = @poller.readables.include?(@frontend_socket)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def frontend_poll_weight
|
|
86
|
+
@frontend_poll_weight ||= [ENV["PB_ZMQ_SERVER_FRONTEND_POLL_WEIGHT"].to_i, 1].max
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def init_backend_socket
|
|
90
|
+
@backend_socket = @zmq_context.socket(ZMQ::ROUTER)
|
|
91
|
+
zmq_error_check(@backend_socket.bind(@server.backend_uri))
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def init_frontend_socket
|
|
95
|
+
@frontend_socket = @zmq_context.socket(ZMQ::ROUTER)
|
|
96
|
+
zmq_error_check(@frontend_socket.bind(@server.frontend_uri))
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def init_local_queue
|
|
100
|
+
@local_queue = []
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def init_poller
|
|
104
|
+
@poller = ZMQ::Poller.new
|
|
105
|
+
@poller.register_readable(@frontend_socket)
|
|
106
|
+
@poller.register_readable(@backend_socket)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def init_zmq_context
|
|
110
|
+
if inproc?
|
|
111
|
+
@zmq_context = @server.zmq_context
|
|
112
|
+
else
|
|
113
|
+
@zmq_context = ZMQ::Context.new
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def inproc?
|
|
118
|
+
!!@server.try(:inproc?)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def local_queue_available?
|
|
122
|
+
local_queue.size < local_queue_max_size && running?
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def local_queue_max_size
|
|
126
|
+
@local_queue_max_size ||= [ENV["PB_ZMQ_SERVER_QUEUE_MAX_SIZE"].to_i, 5].max
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def process_backend
|
|
130
|
+
worker, _ignore, *frames = read_from_backend
|
|
131
|
+
|
|
132
|
+
@idle_workers << worker
|
|
133
|
+
|
|
134
|
+
unless frames == [::Protobuf::Rpc::Zmq::WORKER_READY_MESSAGE]
|
|
135
|
+
write_to_frontend(frames)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
|
139
|
+
def process_frontend
|
|
140
|
+
address, _, message, *frames = read_from_frontend
|
|
141
|
+
|
|
142
|
+
if message == ::Protobuf::Rpc::Zmq::CHECK_AVAILABLE_MESSAGE
|
|
143
|
+
if local_queue_available?
|
|
144
|
+
write_to_frontend([address, ::Protobuf::Rpc::Zmq::EMPTY_STRING, ::Protobuf::Rpc::Zmq::WORKERS_AVAILABLE])
|
|
145
|
+
else
|
|
146
|
+
write_to_frontend([address, ::Protobuf::Rpc::Zmq::EMPTY_STRING, ::Protobuf::Rpc::Zmq::NO_WORKERS_AVAILABLE])
|
|
147
|
+
end
|
|
148
|
+
else
|
|
149
|
+
if @idle_workers.empty?
|
|
150
|
+
local_queue << [address, ::Protobuf::Rpc::Zmq::EMPTY_STRING, message].concat(frames)
|
|
151
|
+
else
|
|
152
|
+
write_to_backend([@idle_workers.shift, ::Protobuf::Rpc::Zmq::EMPTY_STRING].concat([address, ::Protobuf::Rpc::Zmq::EMPTY_STRING, message]).concat(frames))
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def process_local_queue
|
|
158
|
+
return if local_queue.empty?
|
|
159
|
+
return if @idle_workers.empty?
|
|
160
|
+
|
|
161
|
+
write_to_backend([@idle_workers.shift, ::Protobuf::Rpc::Zmq::EMPTY_STRING].concat(local_queue.shift))
|
|
162
|
+
process_local_queue
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def read_from_backend
|
|
166
|
+
frames = []
|
|
167
|
+
zmq_error_check(@backend_socket.recv_strings(frames))
|
|
168
|
+
frames
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def read_from_frontend
|
|
172
|
+
frames = []
|
|
173
|
+
zmq_error_check(@frontend_socket.recv_strings(frames))
|
|
174
|
+
frames
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def teardown
|
|
178
|
+
@frontend_socket.try(:close)
|
|
179
|
+
@backend_socket.try(:close)
|
|
180
|
+
@zmq_context.try(:terminate) unless inproc?
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def write_to_backend(frames)
|
|
184
|
+
zmq_error_check(@backend_socket.send_strings(frames))
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def write_to_frontend(frames)
|
|
188
|
+
zmq_error_check(@frontend_socket.send_strings(frames))
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|
|
193
|
+
end
|