protobuf-cucumber 3.10.4
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 +70 -0
- data/.rubocop_todo.yml +145 -0
- data/.travis.yml +40 -0
- data/.yardopts +5 -0
- data/CHANGES.md +344 -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 +22 -0
- data/bin/rpc_server +5 -0
- data/install-protobuf.sh +28 -0
- data/lib/protobuf.rb +129 -0
- data/lib/protobuf/cli.rb +257 -0
- data/lib/protobuf/code_generator.rb +120 -0
- data/lib/protobuf/decoder.rb +28 -0
- data/lib/protobuf/deprecation.rb +117 -0
- data/lib/protobuf/descriptors.rb +3 -0
- data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +62 -0
- data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +301 -0
- data/lib/protobuf/encoder.rb +11 -0
- data/lib/protobuf/enum.rb +365 -0
- data/lib/protobuf/exceptions.rb +9 -0
- data/lib/protobuf/field.rb +74 -0
- data/lib/protobuf/field/base_field.rb +380 -0
- data/lib/protobuf/field/base_field_object_definitions.rb +504 -0
- data/lib/protobuf/field/bool_field.rb +64 -0
- data/lib/protobuf/field/bytes_field.rb +78 -0
- data/lib/protobuf/field/double_field.rb +25 -0
- data/lib/protobuf/field/enum_field.rb +61 -0
- data/lib/protobuf/field/field_array.rb +104 -0
- data/lib/protobuf/field/field_hash.rb +122 -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 +43 -0
- data/lib/protobuf/field/int32_field.rb +21 -0
- data/lib/protobuf/field/int64_field.rb +34 -0
- data/lib/protobuf/field/integer_field.rb +23 -0
- data/lib/protobuf/field/message_field.rb +51 -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 +51 -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 +77 -0
- data/lib/protobuf/generators/base.rb +85 -0
- data/lib/protobuf/generators/enum_generator.rb +39 -0
- data/lib/protobuf/generators/extension_generator.rb +27 -0
- data/lib/protobuf/generators/field_generator.rb +193 -0
- data/lib/protobuf/generators/file_generator.rb +262 -0
- data/lib/protobuf/generators/group_generator.rb +122 -0
- data/lib/protobuf/generators/message_generator.rb +104 -0
- data/lib/protobuf/generators/option_generator.rb +17 -0
- data/lib/protobuf/generators/printable.rb +160 -0
- data/lib/protobuf/generators/service_generator.rb +50 -0
- data/lib/protobuf/lifecycle.rb +33 -0
- data/lib/protobuf/logging.rb +39 -0
- data/lib/protobuf/message.rb +260 -0
- data/lib/protobuf/message/fields.rb +233 -0
- data/lib/protobuf/message/serialization.rb +85 -0
- data/lib/protobuf/optionable.rb +70 -0
- data/lib/protobuf/rpc/buffer.rb +78 -0
- data/lib/protobuf/rpc/client.rb +140 -0
- data/lib/protobuf/rpc/connectors/base.rb +221 -0
- data/lib/protobuf/rpc/connectors/ping.rb +89 -0
- data/lib/protobuf/rpc/connectors/socket.rb +78 -0
- data/lib/protobuf/rpc/connectors/zmq.rb +319 -0
- data/lib/protobuf/rpc/dynamic_discovery.pb.rb +50 -0
- data/lib/protobuf/rpc/env.rb +60 -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 +40 -0
- data/lib/protobuf/rpc/middleware/logger.rb +95 -0
- data/lib/protobuf/rpc/middleware/request_decoder.rb +79 -0
- data/lib/protobuf/rpc/middleware/response_encoder.rb +83 -0
- data/lib/protobuf/rpc/middleware/runner.rb +18 -0
- data/lib/protobuf/rpc/rpc.pb.rb +64 -0
- data/lib/protobuf/rpc/rpc_method.rb +16 -0
- data/lib/protobuf/rpc/server.rb +39 -0
- data/lib/protobuf/rpc/servers/socket/server.rb +121 -0
- data/lib/protobuf/rpc/servers/socket/worker.rb +56 -0
- data/lib/protobuf/rpc/servers/socket_runner.rb +46 -0
- data/lib/protobuf/rpc/servers/zmq/broker.rb +194 -0
- data/lib/protobuf/rpc/servers/zmq/server.rb +321 -0
- data/lib/protobuf/rpc/servers/zmq/util.rb +48 -0
- data/lib/protobuf/rpc/servers/zmq/worker.rb +105 -0
- data/lib/protobuf/rpc/servers/zmq_runner.rb +70 -0
- data/lib/protobuf/rpc/service.rb +172 -0
- data/lib/protobuf/rpc/service_directory.rb +261 -0
- data/lib/protobuf/rpc/service_dispatcher.rb +45 -0
- data/lib/protobuf/rpc/service_filters.rb +250 -0
- data/lib/protobuf/rpc/stat.rb +119 -0
- data/lib/protobuf/socket.rb +21 -0
- data/lib/protobuf/tasks.rb +1 -0
- data/lib/protobuf/tasks/compile.rake +80 -0
- data/lib/protobuf/varint.rb +20 -0
- data/lib/protobuf/varint_pure.rb +31 -0
- data/lib/protobuf/version.rb +3 -0
- data/lib/protobuf/wire_type.rb +10 -0
- data/lib/protobuf/zmq.rb +21 -0
- data/profile.html +5103 -0
- data/proto/dynamic_discovery.proto +44 -0
- data/proto/google/protobuf/compiler/plugin.proto +147 -0
- data/proto/google/protobuf/descriptor.proto +779 -0
- data/proto/rpc.proto +69 -0
- data/protobuf-cucumber.gemspec +57 -0
- data/spec/benchmark/tasks.rb +143 -0
- data/spec/bin/protoc-gen-ruby_spec.rb +23 -0
- data/spec/encoding/all_types_spec.rb +103 -0
- data/spec/encoding/extreme_values_spec.rb +0 -0
- data/spec/functional/class_inheritance_spec.rb +52 -0
- data/spec/functional/code_generator_spec.rb +58 -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 +317 -0
- data/spec/lib/protobuf/code_generator_spec.rb +87 -0
- data/spec/lib/protobuf/enum_spec.rb +307 -0
- data/spec/lib/protobuf/field/bool_field_spec.rb +91 -0
- data/spec/lib/protobuf/field/double_field_spec.rb +9 -0
- data/spec/lib/protobuf/field/enum_field_spec.rb +44 -0
- data/spec/lib/protobuf/field/field_array_spec.rb +105 -0
- data/spec/lib/protobuf/field/field_hash_spec.rb +168 -0
- data/spec/lib/protobuf/field/fixed32_field_spec.rb +7 -0
- data/spec/lib/protobuf/field/fixed64_field_spec.rb +7 -0
- data/spec/lib/protobuf/field/float_field_spec.rb +90 -0
- data/spec/lib/protobuf/field/int32_field_spec.rb +120 -0
- data/spec/lib/protobuf/field/int64_field_spec.rb +7 -0
- data/spec/lib/protobuf/field/message_field_spec.rb +132 -0
- data/spec/lib/protobuf/field/sfixed32_field_spec.rb +9 -0
- data/spec/lib/protobuf/field/sfixed64_field_spec.rb +9 -0
- data/spec/lib/protobuf/field/sint32_field_spec.rb +9 -0
- data/spec/lib/protobuf/field/sint64_field_spec.rb +9 -0
- data/spec/lib/protobuf/field/string_field_spec.rb +79 -0
- data/spec/lib/protobuf/field/uint32_field_spec.rb +7 -0
- data/spec/lib/protobuf/field/uint64_field_spec.rb +7 -0
- data/spec/lib/protobuf/field_spec.rb +192 -0
- data/spec/lib/protobuf/generators/base_spec.rb +154 -0
- data/spec/lib/protobuf/generators/enum_generator_spec.rb +82 -0
- data/spec/lib/protobuf/generators/extension_generator_spec.rb +42 -0
- data/spec/lib/protobuf/generators/field_generator_spec.rb +197 -0
- data/spec/lib/protobuf/generators/file_generator_spec.rb +119 -0
- data/spec/lib/protobuf/generators/message_generator_spec.rb +0 -0
- data/spec/lib/protobuf/generators/service_generator_spec.rb +99 -0
- data/spec/lib/protobuf/lifecycle_spec.rb +94 -0
- data/spec/lib/protobuf/message_spec.rb +944 -0
- data/spec/lib/protobuf/optionable_spec.rb +265 -0
- data/spec/lib/protobuf/rpc/client_spec.rb +66 -0
- data/spec/lib/protobuf/rpc/connectors/base_spec.rb +226 -0
- data/spec/lib/protobuf/rpc/connectors/ping_spec.rb +69 -0
- data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +34 -0
- data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +110 -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 +91 -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 +35 -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 +101 -0
- data/spec/lib/protobuf/varint_spec.rb +29 -0
- data/spec/lib/protobuf_spec.rb +105 -0
- data/spec/spec_helper.rb +42 -0
- data/spec/support/all.rb +6 -0
- data/spec/support/packed_field.rb +23 -0
- data/spec/support/protos/all_types.data.bin +0 -0
- data/spec/support/protos/all_types.data.txt +119 -0
- data/spec/support/protos/enum.pb.rb +63 -0
- data/spec/support/protos/enum.proto +37 -0
- data/spec/support/protos/extreme_values.data.bin +0 -0
- data/spec/support/protos/google_unittest.bin +0 -0
- data/spec/support/protos/google_unittest.pb.rb +798 -0
- data/spec/support/protos/google_unittest.proto +884 -0
- data/spec/support/protos/google_unittest_custom_options.bin +0 -0
- data/spec/support/protos/google_unittest_custom_options.pb.rb +361 -0
- data/spec/support/protos/google_unittest_custom_options.proto +424 -0
- data/spec/support/protos/google_unittest_import.pb.rb +55 -0
- data/spec/support/protos/google_unittest_import.proto +73 -0
- data/spec/support/protos/google_unittest_import_public.pb.rb +31 -0
- data/spec/support/protos/google_unittest_import_public.proto +41 -0
- data/spec/support/protos/map-test.bin +157 -0
- data/spec/support/protos/map-test.pb.rb +85 -0
- data/spec/support/protos/map-test.proto +68 -0
- data/spec/support/protos/multi_field_extensions.pb.rb +59 -0
- data/spec/support/protos/multi_field_extensions.proto +35 -0
- data/spec/support/protos/resource.pb.rb +172 -0
- data/spec/support/protos/resource.proto +137 -0
- data/spec/support/resource_service.rb +23 -0
- data/spec/support/server.rb +65 -0
- data/spec/support/test_app_file.rb +2 -0
- data/varint_prof.rb +82 -0
- metadata +579 -0
@@ -0,0 +1,83 @@
|
|
1
|
+
module Protobuf
|
2
|
+
module Rpc
|
3
|
+
module Middleware
|
4
|
+
class ResponseEncoder
|
5
|
+
include ::Protobuf::Logging
|
6
|
+
|
7
|
+
attr_reader :app, :env
|
8
|
+
|
9
|
+
def initialize(app)
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
dup._call(env)
|
15
|
+
end
|
16
|
+
|
17
|
+
def _call(env)
|
18
|
+
@env = app.call(env)
|
19
|
+
|
20
|
+
env.response = response
|
21
|
+
env.encoded_response = encoded_response
|
22
|
+
env
|
23
|
+
end
|
24
|
+
|
25
|
+
def log_signature
|
26
|
+
env.log_signature || super
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
# Encode the response wrapper to return to the client
|
32
|
+
#
|
33
|
+
def encoded_response
|
34
|
+
logger.debug { sign_message("Encoding response: #{response.inspect}") }
|
35
|
+
|
36
|
+
env.encoded_response = wrapped_response.encode
|
37
|
+
rescue => exception
|
38
|
+
log_exception(exception)
|
39
|
+
|
40
|
+
# Rescue encoding exceptions, re-wrap them as generic protobuf errors,
|
41
|
+
# and re-raise them
|
42
|
+
raise PbError, exception.message
|
43
|
+
end
|
44
|
+
|
45
|
+
# Prod the object to see if we can produce a proto object as a response
|
46
|
+
# candidate. Validate the candidate protos.
|
47
|
+
def response
|
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)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Ensure that the response candidate we've been given is of the type
|
60
|
+
# we expect so that deserialization on the client side works.
|
61
|
+
#
|
62
|
+
def validate!(candidate)
|
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}"
|
65
|
+
end
|
66
|
+
|
67
|
+
candidate
|
68
|
+
end
|
69
|
+
|
70
|
+
# The middleware stack returns either an error or response proto. Package
|
71
|
+
# it up so that it's in the correct spot in the response wrapper
|
72
|
+
#
|
73
|
+
def wrapped_response
|
74
|
+
if response.is_a?(::Protobuf::Rpc::PbError)
|
75
|
+
::Protobuf::Socketrpc::Response.new(:error => response.message, :error_reason => response.error_type, :server => env.server)
|
76
|
+
else
|
77
|
+
::Protobuf::Socketrpc::Response.new(:response_proto => response.encode, :server => env.server)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
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,64 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
##
|
4
|
+
# This file is auto-generated. DO NOT EDIT!
|
5
|
+
#
|
6
|
+
require 'protobuf'
|
7
|
+
|
8
|
+
module Protobuf
|
9
|
+
module Socketrpc
|
10
|
+
::Protobuf::Optionable.inject(self) { ::Google::Protobuf::FileOptions }
|
11
|
+
|
12
|
+
##
|
13
|
+
# Enum Classes
|
14
|
+
#
|
15
|
+
class ErrorReason < ::Protobuf::Enum
|
16
|
+
define :BAD_REQUEST_DATA, 0
|
17
|
+
define :BAD_REQUEST_PROTO, 1
|
18
|
+
define :SERVICE_NOT_FOUND, 2
|
19
|
+
define :METHOD_NOT_FOUND, 3
|
20
|
+
define :RPC_ERROR, 4
|
21
|
+
define :RPC_FAILED, 5
|
22
|
+
define :INVALID_REQUEST_PROTO, 6
|
23
|
+
define :BAD_RESPONSE_PROTO, 7
|
24
|
+
define :UNKNOWN_HOST, 8
|
25
|
+
define :IO_ERROR, 9
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
##
|
30
|
+
# Message Classes
|
31
|
+
#
|
32
|
+
class Request < ::Protobuf::Message; end
|
33
|
+
class Response < ::Protobuf::Message; end
|
34
|
+
class Header < ::Protobuf::Message; end
|
35
|
+
|
36
|
+
|
37
|
+
##
|
38
|
+
# Message Fields
|
39
|
+
#
|
40
|
+
class Request
|
41
|
+
required :string, :service_name, 1
|
42
|
+
required :string, :method_name, 2
|
43
|
+
optional :bytes, :request_proto, 3
|
44
|
+
optional :string, :caller, 4
|
45
|
+
repeated ::Protobuf::Socketrpc::Header, :headers, 5
|
46
|
+
end
|
47
|
+
|
48
|
+
class Response
|
49
|
+
optional :bytes, :response_proto, 1
|
50
|
+
optional :string, :error, 2
|
51
|
+
optional :bool, :callback, 3, :default => false
|
52
|
+
optional ::Protobuf::Socketrpc::ErrorReason, :error_reason, 4
|
53
|
+
optional :string, :server, 5
|
54
|
+
end
|
55
|
+
|
56
|
+
class Header
|
57
|
+
required :string, :key, 1
|
58
|
+
optional :string, :value, 2
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
|
@@ -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
|
@@ -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, env_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(env_data.merge('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,121 @@
|
|
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 :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.empty? && 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, &:close)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def run
|
68
|
+
logger.debug { sign_message("Run") }
|
69
|
+
|
70
|
+
server = ::TCPServer.new(host, port)
|
71
|
+
fail "The server was unable to start properly." if server.closed?
|
72
|
+
|
73
|
+
begin
|
74
|
+
server.listen(backlog)
|
75
|
+
listen_fds = [server]
|
76
|
+
self.running = true
|
77
|
+
|
78
|
+
while running?
|
79
|
+
logger.debug { sign_message("Waiting for connections") }
|
80
|
+
ready_cnxns = begin
|
81
|
+
IO.select(listen_fds, [], [], AUTO_COLLECT_TIMEOUT)
|
82
|
+
rescue IOError
|
83
|
+
nil
|
84
|
+
end
|
85
|
+
|
86
|
+
if ready_cnxns
|
87
|
+
ready_cnxns.first.each do |client|
|
88
|
+
case
|
89
|
+
when !running?
|
90
|
+
# no-op
|
91
|
+
when client == server
|
92
|
+
logger.debug { sign_message("Accepted new connection") }
|
93
|
+
client, _sockaddr = server.accept
|
94
|
+
listen_fds << client
|
95
|
+
else
|
96
|
+
unless working.include?(client)
|
97
|
+
working << listen_fds.delete(client)
|
98
|
+
logger.debug { sign_message("Working") }
|
99
|
+
threads << { :thread => new_worker(client), :socket => client }
|
100
|
+
|
101
|
+
cleanup_threads if cleanup?
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
elsif threads.size > 1
|
106
|
+
# Run a cleanup if select times out while waiting
|
107
|
+
cleanup_threads
|
108
|
+
end
|
109
|
+
end
|
110
|
+
ensure
|
111
|
+
server.close
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def stop
|
116
|
+
self.running = false
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
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,46 @@
|
|
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.respond_to?(:to_hash) then
|
16
|
+
options.to_hash.symbolize_keys
|
17
|
+
else
|
18
|
+
fail "Cannot parser Socket Server - server options"
|
19
|
+
end
|
20
|
+
|
21
|
+
self.server = ::Protobuf::Rpc::Socket::Server.new(options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def run
|
25
|
+
yield if block_given?
|
26
|
+
server.run
|
27
|
+
end
|
28
|
+
|
29
|
+
def running?
|
30
|
+
server.running?
|
31
|
+
end
|
32
|
+
|
33
|
+
def stop
|
34
|
+
server.stop
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
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
|