protobuffy 3.1.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.
Files changed (192) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.travis.yml +12 -0
  4. data/.yardopts +5 -0
  5. data/CHANGES.md +261 -0
  6. data/CONTRIBUTING.md +16 -0
  7. data/Gemfile +3 -0
  8. data/LICENSE.txt +14 -0
  9. data/README.md +58 -0
  10. data/Rakefile +61 -0
  11. data/bin/protoc-gen-ruby +17 -0
  12. data/bin/rpc_server +4 -0
  13. data/examples/bin/reverse-client-http +4 -0
  14. data/examples/bin/reverse-client-socket +4 -0
  15. data/examples/bin/reverse-client-zmq +4 -0
  16. data/examples/config.ru +6 -0
  17. data/examples/definitions/example/reverse.proto +12 -0
  18. data/examples/lib/example/reverse-client.rb +23 -0
  19. data/examples/lib/example/reverse-service.rb +9 -0
  20. data/examples/lib/example/reverse.pb.rb +36 -0
  21. data/lib/protobuf.rb +106 -0
  22. data/lib/protobuf/cli.rb +249 -0
  23. data/lib/protobuf/code_generator.rb +41 -0
  24. data/lib/protobuf/decoder.rb +74 -0
  25. data/lib/protobuf/deprecator.rb +42 -0
  26. data/lib/protobuf/descriptors.rb +3 -0
  27. data/lib/protobuf/descriptors/google/protobuf/compiler/plugin.pb.rb +52 -0
  28. data/lib/protobuf/descriptors/google/protobuf/descriptor.pb.rb +249 -0
  29. data/lib/protobuf/encoder.rb +62 -0
  30. data/lib/protobuf/enum.rb +319 -0
  31. data/lib/protobuf/exceptions.rb +9 -0
  32. data/lib/protobuf/field.rb +74 -0
  33. data/lib/protobuf/field/base_field.rb +280 -0
  34. data/lib/protobuf/field/bool_field.rb +53 -0
  35. data/lib/protobuf/field/bytes_field.rb +81 -0
  36. data/lib/protobuf/field/double_field.rb +26 -0
  37. data/lib/protobuf/field/enum_field.rb +57 -0
  38. data/lib/protobuf/field/field_array.rb +86 -0
  39. data/lib/protobuf/field/fixed32_field.rb +25 -0
  40. data/lib/protobuf/field/fixed64_field.rb +29 -0
  41. data/lib/protobuf/field/float_field.rb +38 -0
  42. data/lib/protobuf/field/int32_field.rb +22 -0
  43. data/lib/protobuf/field/int64_field.rb +22 -0
  44. data/lib/protobuf/field/integer_field.rb +24 -0
  45. data/lib/protobuf/field/message_field.rb +66 -0
  46. data/lib/protobuf/field/sfixed32_field.rb +28 -0
  47. data/lib/protobuf/field/sfixed64_field.rb +29 -0
  48. data/lib/protobuf/field/signed_integer_field.rb +30 -0
  49. data/lib/protobuf/field/sint32_field.rb +22 -0
  50. data/lib/protobuf/field/sint64_field.rb +22 -0
  51. data/lib/protobuf/field/string_field.rb +35 -0
  52. data/lib/protobuf/field/uint32_field.rb +22 -0
  53. data/lib/protobuf/field/uint64_field.rb +22 -0
  54. data/lib/protobuf/field/varint_field.rb +68 -0
  55. data/lib/protobuf/generators/base.rb +71 -0
  56. data/lib/protobuf/generators/enum_generator.rb +42 -0
  57. data/lib/protobuf/generators/extension_generator.rb +28 -0
  58. data/lib/protobuf/generators/field_generator.rb +132 -0
  59. data/lib/protobuf/generators/file_generator.rb +140 -0
  60. data/lib/protobuf/generators/group_generator.rb +113 -0
  61. data/lib/protobuf/generators/message_generator.rb +99 -0
  62. data/lib/protobuf/generators/printable.rb +161 -0
  63. data/lib/protobuf/generators/service_generator.rb +27 -0
  64. data/lib/protobuf/http.rb +20 -0
  65. data/lib/protobuf/lifecycle.rb +46 -0
  66. data/lib/protobuf/logger.rb +86 -0
  67. data/lib/protobuf/message.rb +182 -0
  68. data/lib/protobuf/message/fields.rb +122 -0
  69. data/lib/protobuf/message/serialization.rb +84 -0
  70. data/lib/protobuf/optionable.rb +23 -0
  71. data/lib/protobuf/rpc/buffer.rb +79 -0
  72. data/lib/protobuf/rpc/client.rb +168 -0
  73. data/lib/protobuf/rpc/connector.rb +21 -0
  74. data/lib/protobuf/rpc/connectors/base.rb +54 -0
  75. data/lib/protobuf/rpc/connectors/common.rb +172 -0
  76. data/lib/protobuf/rpc/connectors/http.rb +90 -0
  77. data/lib/protobuf/rpc/connectors/socket.rb +73 -0
  78. data/lib/protobuf/rpc/connectors/zmq.rb +205 -0
  79. data/lib/protobuf/rpc/dynamic_discovery.pb.rb +47 -0
  80. data/lib/protobuf/rpc/env.rb +58 -0
  81. data/lib/protobuf/rpc/error.rb +28 -0
  82. data/lib/protobuf/rpc/error/client_error.rb +31 -0
  83. data/lib/protobuf/rpc/error/server_error.rb +43 -0
  84. data/lib/protobuf/rpc/middleware.rb +25 -0
  85. data/lib/protobuf/rpc/middleware/exception_handler.rb +36 -0
  86. data/lib/protobuf/rpc/middleware/logger.rb +91 -0
  87. data/lib/protobuf/rpc/middleware/request_decoder.rb +83 -0
  88. data/lib/protobuf/rpc/middleware/response_encoder.rb +88 -0
  89. data/lib/protobuf/rpc/middleware/runner.rb +18 -0
  90. data/lib/protobuf/rpc/rpc.pb.rb +53 -0
  91. data/lib/protobuf/rpc/server.rb +39 -0
  92. data/lib/protobuf/rpc/servers/http/server.rb +101 -0
  93. data/lib/protobuf/rpc/servers/http_runner.rb +34 -0
  94. data/lib/protobuf/rpc/servers/socket/server.rb +113 -0
  95. data/lib/protobuf/rpc/servers/socket/worker.rb +56 -0
  96. data/lib/protobuf/rpc/servers/socket_runner.rb +34 -0
  97. data/lib/protobuf/rpc/servers/zmq/broker.rb +155 -0
  98. data/lib/protobuf/rpc/servers/zmq/server.rb +313 -0
  99. data/lib/protobuf/rpc/servers/zmq/util.rb +47 -0
  100. data/lib/protobuf/rpc/servers/zmq/worker.rb +105 -0
  101. data/lib/protobuf/rpc/servers/zmq_runner.rb +51 -0
  102. data/lib/protobuf/rpc/service.rb +179 -0
  103. data/lib/protobuf/rpc/service_directory.rb +245 -0
  104. data/lib/protobuf/rpc/service_dispatcher.rb +46 -0
  105. data/lib/protobuf/rpc/service_filters.rb +273 -0
  106. data/lib/protobuf/rpc/stat.rb +148 -0
  107. data/lib/protobuf/socket.rb +22 -0
  108. data/lib/protobuf/tasks.rb +1 -0
  109. data/lib/protobuf/tasks/compile.rake +61 -0
  110. data/lib/protobuf/version.rb +3 -0
  111. data/lib/protobuf/wire_type.rb +10 -0
  112. data/lib/protobuf/zmq.rb +21 -0
  113. data/proto/dynamic_discovery.proto +44 -0
  114. data/proto/google/protobuf/compiler/plugin.proto +147 -0
  115. data/proto/google/protobuf/descriptor.proto +620 -0
  116. data/proto/rpc.proto +62 -0
  117. data/protobuffy.gemspec +37 -0
  118. data/spec/benchmark/tasks.rb +113 -0
  119. data/spec/bin/protoc-gen-ruby_spec.rb +18 -0
  120. data/spec/data/data.bin +3 -0
  121. data/spec/data/types.bin +0 -0
  122. data/spec/encoding/all_types_spec.rb +91 -0
  123. data/spec/encoding/extreme_values_spec.rb +0 -0
  124. data/spec/functional/socket_server_spec.rb +59 -0
  125. data/spec/functional/zmq_server_spec.rb +103 -0
  126. data/spec/lib/protobuf/cli_spec.rb +267 -0
  127. data/spec/lib/protobuf/code_generator_spec.rb +60 -0
  128. data/spec/lib/protobuf/enum_spec.rb +239 -0
  129. data/spec/lib/protobuf/field/int32_field_spec.rb +7 -0
  130. data/spec/lib/protobuf/field/string_field_spec.rb +46 -0
  131. data/spec/lib/protobuf/field_spec.rb +194 -0
  132. data/spec/lib/protobuf/generators/base_spec.rb +87 -0
  133. data/spec/lib/protobuf/generators/enum_generator_spec.rb +68 -0
  134. data/spec/lib/protobuf/generators/extension_generator_spec.rb +43 -0
  135. data/spec/lib/protobuf/generators/field_generator_spec.rb +99 -0
  136. data/spec/lib/protobuf/generators/file_generator_spec.rb +29 -0
  137. data/spec/lib/protobuf/generators/message_generator_spec.rb +0 -0
  138. data/spec/lib/protobuf/generators/service_generator_spec.rb +43 -0
  139. data/spec/lib/protobuf/lifecycle_spec.rb +89 -0
  140. data/spec/lib/protobuf/logger_spec.rb +136 -0
  141. data/spec/lib/protobuf/message_spec.rb +368 -0
  142. data/spec/lib/protobuf/optionable_spec.rb +46 -0
  143. data/spec/lib/protobuf/rpc/client_spec.rb +66 -0
  144. data/spec/lib/protobuf/rpc/connector_spec.rb +26 -0
  145. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +50 -0
  146. data/spec/lib/protobuf/rpc/connectors/common_spec.rb +170 -0
  147. data/spec/lib/protobuf/rpc/connectors/connector_spec.rb +13 -0
  148. data/spec/lib/protobuf/rpc/connectors/http_spec.rb +61 -0
  149. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +24 -0
  150. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +129 -0
  151. data/spec/lib/protobuf/rpc/middleware/exception_handler_spec.rb +62 -0
  152. data/spec/lib/protobuf/rpc/middleware/logger_spec.rb +49 -0
  153. data/spec/lib/protobuf/rpc/middleware/request_decoder_spec.rb +115 -0
  154. data/spec/lib/protobuf/rpc/middleware/response_encoder_spec.rb +75 -0
  155. data/spec/lib/protobuf/rpc/servers/http/server_spec.rb +104 -0
  156. data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +38 -0
  157. data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +41 -0
  158. data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +55 -0
  159. data/spec/lib/protobuf/rpc/servers/zmq/worker_spec.rb +35 -0
  160. data/spec/lib/protobuf/rpc/service_directory_spec.rb +295 -0
  161. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +52 -0
  162. data/spec/lib/protobuf/rpc/service_filters_spec.rb +484 -0
  163. data/spec/lib/protobuf/rpc/service_spec.rb +161 -0
  164. data/spec/lib/protobuf/rpc/stat_spec.rb +151 -0
  165. data/spec/lib/protobuf_spec.rb +78 -0
  166. data/spec/spec_helper.rb +57 -0
  167. data/spec/support/all.rb +7 -0
  168. data/spec/support/packed_field.rb +22 -0
  169. data/spec/support/server.rb +94 -0
  170. data/spec/support/test/all_types.data.bin +0 -0
  171. data/spec/support/test/all_types.data.txt +119 -0
  172. data/spec/support/test/defaults.pb.rb +25 -0
  173. data/spec/support/test/defaults.proto +9 -0
  174. data/spec/support/test/enum.pb.rb +59 -0
  175. data/spec/support/test/enum.proto +34 -0
  176. data/spec/support/test/extended.pb.rb +22 -0
  177. data/spec/support/test/extended.proto +10 -0
  178. data/spec/support/test/extreme_values.data.bin +0 -0
  179. data/spec/support/test/google_unittest.pb.rb +543 -0
  180. data/spec/support/test/google_unittest.proto +713 -0
  181. data/spec/support/test/google_unittest_import.pb.rb +37 -0
  182. data/spec/support/test/google_unittest_import.proto +64 -0
  183. data/spec/support/test/google_unittest_import_public.pb.rb +8 -0
  184. data/spec/support/test/google_unittest_import_public.proto +38 -0
  185. data/spec/support/test/multi_field_extensions.pb.rb +56 -0
  186. data/spec/support/test/multi_field_extensions.proto +33 -0
  187. data/spec/support/test/resource.pb.rb +117 -0
  188. data/spec/support/test/resource.proto +94 -0
  189. data/spec/support/test/resource_service.rb +26 -0
  190. data/spec/support/test_app_file.rb +2 -0
  191. data/spec/support/tolerance_matcher.rb +40 -0
  192. metadata +367 -0
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Before requiring protobuf, ensure that we will not load any
4
+ # server or client code.
5
+ #
6
+ ENV['PB_NO_NETWORKING'] = '1'
7
+
8
+ $LOAD_PATH << ::File.expand_path("../../lib", __FILE__)
9
+ require 'protobuf'
10
+ require 'protobuf/descriptors'
11
+ require 'protobuf/code_generator'
12
+
13
+ request_bytes = STDIN.read
14
+ code_generator = ::Protobuf::CodeGenerator.new(request_bytes)
15
+ response_bytes = code_generator.response_bytes
16
+ STDOUT.print(response_bytes)
17
+
data/bin/rpc_server ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'protobuf/cli'
4
+ ::Protobuf::CLI.start(ARGV)
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "protobuf/http"
4
+ require_relative "../lib/example/reverse-client.rb"
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "protobuf/socket"
4
+ require_relative "../lib/example/reverse-client.rb"
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "protobuf/zmq"
4
+ require_relative "../lib/example/reverse-client.rb"
@@ -0,0 +1,6 @@
1
+ require "protobuf"
2
+ require "protobuf/rpc/servers/http/server"
3
+
4
+ require_relative "lib/example/reverse-service"
5
+
6
+ run Protobuf::Rpc::Http::Server.new
@@ -0,0 +1,12 @@
1
+ // definitions/example/reverse.proto
2
+ package example;
3
+
4
+ message ReverseRequest {
5
+ required string input = 1;
6
+ }
7
+ message ReverseResponse {
8
+ required string reversed = 1;
9
+ }
10
+ service ReverseService {
11
+ rpc Reverse (ReverseRequest) returns (ReverseResponse);
12
+ }
@@ -0,0 +1,23 @@
1
+ require "protobuf"
2
+
3
+ require_relative "reverse.pb.rb"
4
+
5
+ # Protobuf::Logger.configure :level => Protobuf::Logger::DEBUG, :file => "./log/protobuf-client.log"
6
+
7
+ configuration = {
8
+ :host => "localhost",
9
+ :port => 9399
10
+ }
11
+
12
+ request = {
13
+ :input => (ARGV[0] or 'hello world')
14
+ }
15
+
16
+ Example::ReverseService.client(configuration).reverse(Example::ReverseRequest.new(request)) do |client|
17
+ client.on_success do |response|
18
+ puts response.reversed
19
+ end
20
+ client.on_failure do |error|
21
+ puts 'It failed: ' + error.message
22
+ end
23
+ end
@@ -0,0 +1,9 @@
1
+ require_relative "reverse.pb.rb"
2
+
3
+ module Example
4
+ class ReverseService
5
+ def reverse
6
+ respond_with :reversed => request.input.reverse
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,36 @@
1
+ ##
2
+ # This file is auto-generated. DO NOT EDIT!
3
+ #
4
+ require 'protobuf/message'
5
+ require 'protobuf/rpc/service'
6
+
7
+ module Example
8
+
9
+ ##
10
+ # Message Classes
11
+ #
12
+ class ReverseRequest < ::Protobuf::Message; end
13
+ class ReverseResponse < ::Protobuf::Message; end
14
+
15
+
16
+ ##
17
+ # Message Fields
18
+ #
19
+ class ReverseRequest
20
+ required :string, :input, 1
21
+ end
22
+
23
+ class ReverseResponse
24
+ required :string, :reversed, 1
25
+ end
26
+
27
+
28
+ ##
29
+ # Service Classes
30
+ #
31
+ class ReverseService < ::Protobuf::Rpc::Service
32
+ rpc :reverse, ::Example::ReverseRequest, ::Example::ReverseResponse
33
+ end
34
+
35
+ end
36
+
data/lib/protobuf.rb ADDED
@@ -0,0 +1,106 @@
1
+ require 'logger'
2
+ require 'socket'
3
+ require 'pp'
4
+ require 'stringio'
5
+
6
+ require 'active_support/core_ext/object/blank'
7
+ require 'active_support/core_ext/object/try'
8
+ require 'active_support/notifications'
9
+ require 'active_support/inflector'
10
+ require 'active_support/json'
11
+
12
+ module Protobuf
13
+
14
+ # See Protobuf#connector_type documentation.
15
+ CONNECTORS = [ :socket, :zmq, :http ].freeze
16
+
17
+ # Default is Socket as it has no external dependencies.
18
+ DEFAULT_CONNECTOR = :socket
19
+
20
+ module_function
21
+
22
+ # Client Host
23
+ #
24
+ # Default: `hostname` of the system
25
+ #
26
+ # The name or address of the host to use during client RPC calls.
27
+ def self.client_host
28
+ @_client_host ||= `hostname`.chomp
29
+ end
30
+
31
+ def self.client_host=(host)
32
+ @_client_host = host
33
+ end
34
+
35
+ # Connector Type
36
+ #
37
+ # Default: socket
38
+ #
39
+ # Symbol value which denotes the type of connector to use
40
+ # during client requests to an RPC server.
41
+ def self.connector_type
42
+ @_connector_type ||= DEFAULT_CONNECTOR
43
+ end
44
+
45
+ def self.connector_type=(type)
46
+ raise ArgumentError, 'Invalid connector type given' unless CONNECTORS.include?(type)
47
+ @_connector_type = type
48
+ end
49
+
50
+ # GC Pause during server requests
51
+ #
52
+ # Default: false
53
+ #
54
+ # Boolean value to tell the server to disable
55
+ # the Garbage Collector when handling an rpc request.
56
+ # Once the request is completed, the GC is enabled again.
57
+ # This optomization provides a huge boost in speed to rpc requests.
58
+ def self.gc_pause_server_request?
59
+ return @_gc_pause_server_request unless @_gc_pause_server_request.nil?
60
+ self.gc_pause_server_request = false
61
+ end
62
+
63
+ def self.gc_pause_server_request=(value)
64
+ @_gc_pause_server_request = !!value
65
+ end
66
+
67
+ # Print Deprecation Warnings
68
+ #
69
+ # Default: true
70
+ #
71
+ # Simple boolean to define whether we want field deprecation warnings to
72
+ # be printed to stderr or not. The rpc_server has an option to set this value
73
+ # explicitly, or you can turn this option off by setting
74
+ # ENV['PB_IGNORE_DEPRECATIONS'] to a non-empty value.
75
+ #
76
+ # The rpc_server option will override the ENV setting.
77
+ def self.print_deprecation_warnings?
78
+ return @_print_deprecation_warnings unless @_print_deprecation_warnings.nil?
79
+ self.print_deprecation_warnings = ENV.key?('PB_IGNORE_DEPRECATIONS') ? false : true
80
+ end
81
+
82
+ def self.print_deprecation_warnings=(value)
83
+ @_print_deprecation_warnings = !!value
84
+ end
85
+
86
+ end
87
+
88
+ unless ENV.key?('PB_NO_NETWORKING')
89
+ require 'protobuf/rpc/client'
90
+ require 'protobuf/rpc/service'
91
+
92
+ env_connector_type = ENV.fetch('PB_CLIENT_TYPE') {
93
+ ::Protobuf::DEFAULT_CONNECTOR
94
+ }.to_s.downcase.strip.to_sym
95
+
96
+ if ::Protobuf::CONNECTORS.include?(env_connector_type)
97
+ require "protobuf/#{env_connector_type}"
98
+ else
99
+ $stderr.puts <<-WARN
100
+ [WARNING] Require attempted on an invalid connector type '#{env_connector_type}'.
101
+ Falling back to default '#{::Protobuf::DEFAULT_CONNECTOR}' connector.
102
+ WARN
103
+
104
+ require "protobuf/#{::Protobuf::DEFAULT_CONNECTOR}"
105
+ end
106
+ end
@@ -0,0 +1,249 @@
1
+ require 'thor'
2
+ require 'protobuf/version'
3
+ require 'protobuf/logger'
4
+ require 'protobuf/rpc/servers/socket_runner'
5
+ require 'protobuf/rpc/servers/zmq_runner'
6
+ require 'protobuf/rpc/servers/http_runner'
7
+
8
+ module Protobuf
9
+ class CLI < ::Thor
10
+ include ::Thor::Actions
11
+
12
+ attr_accessor :runner, :mode
13
+
14
+ default_task :start
15
+
16
+ desc 'start APP_FILE', 'Run the RPC server in the given mode, preloading the given APP_FILE. This is the default task.'
17
+
18
+ option :host, :type => :string, :default => '127.0.0.1', :aliases => %w(-o), :desc => 'Host to bind.'
19
+ option :port, :type => :numeric, :default => 9399, :aliases => %w(-p), :desc => 'Master Port to bind.'
20
+
21
+ option :backlog, :type => :numeric, :default => 100, :aliases => %w(-b), :desc => 'Backlog for listening socket when using Socket Server.'
22
+ option :threshold, :type => :numeric, :default => 100, :aliases => %w(-t), :desc => 'Multi-threaded Socket Server cleanup threshold.'
23
+ option :threads, :type => :numeric, :default => 5, :aliases => %w(-r), :desc => 'Number of worker threads to run. Only applicable in --zmq mode.'
24
+
25
+ option :log, :type => :string, :aliases => %w(-l), :desc => 'Log file or device. Default is STDOUT.'
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/)'
27
+
28
+ option :socket, :type => :boolean, :aliases => %w(-s), :desc => 'Socket Mode for server and client connections.'
29
+ option :zmq, :type => :boolean, :aliases => %w(-z), :desc => 'ZeroMQ Socket Mode for server and client connections.'
30
+ option :http, :type => :boolean, :aliases => %w(), :desc => 'HTTP Server Mode for server and client connections.'
31
+
32
+ option :beacon_interval, :type => :numeric, :desc => 'Broadcast beacons every N seconds. (default: 5)'
33
+ option :beacon_port, :type => :numeric, :desc => 'Broadcast beacons to this port (default: value of ServiceDirectory.port)'
34
+ option :broadcast_beacons, :type => :boolean, :desc => 'Broadcast beacons for dynamic discovery (Currently only available with ZeroMQ).'
35
+ option :broadcast_busy, :type => :boolean, :default => false, :desc => 'Remove busy nodes from cluster when all workers are busy (Currently only available with ZeroMQ).'
36
+ option :debug, :type => :boolean, :default => false, :aliases => %w(-d), :desc => 'Debug Mode. Override log level to DEBUG.'
37
+ option :gc_pause_request, :type => :boolean, :default => false, :desc => 'Enable/Disable GC pause during request.'
38
+ option :print_deprecation_warnings, :type => :boolean, :default => nil, :desc => 'Cause use of deprecated fields to be printed or ignored.'
39
+ option :workers_only, :type => :boolean, :default => false, :desc => "Starts process with only workers (no broker/frontend is started) only relevant for Zmq Server"
40
+ option :worker_port, :type => :numeric, :default => nil, :desc => "Port for 'backend' where workers connect (defaults to port + 1)"
41
+ option :zmq_inproc, :type => :boolean, :default => true, :desc => 'Use inproc protocol for zmq Server/Broker/Worker'
42
+
43
+ def start(app_file)
44
+ debug_say('Configuring the rpc_server process')
45
+
46
+ configure_logger
47
+ configure_traps
48
+ configure_runner_mode
49
+ create_runner
50
+ configure_process_name(app_file)
51
+ configure_gc
52
+ configure_deprecation_warnings
53
+
54
+ require_application(app_file) unless exit_requested?
55
+ start_server unless exit_requested?
56
+ rescue => e
57
+ say_and_exit('ERROR: RPC Server failed to start.', e)
58
+ end
59
+
60
+ desc 'version', 'Print ruby and protoc versions and exit.'
61
+ def version
62
+ say("Ruby Protobuf v#{::Protobuf::VERSION}")
63
+ end
64
+
65
+ no_tasks do
66
+
67
+ # Tell protobuf how to handle the printing of deprecated field usage.
68
+ def configure_deprecation_warnings
69
+ if options.print_deprecation_warnings.nil?
70
+ ::Protobuf.print_deprecation_warnings = !ENV.key?("PB_IGNORE_DEPRECATIONS")
71
+ else
72
+ ::Protobuf.print_deprecation_warnings = options.print_deprecation_warnings?
73
+ end
74
+ end
75
+
76
+ # If we pause during request we don't need to pause in serialization
77
+ def configure_gc
78
+ debug_say('Configuring gc')
79
+
80
+ if defined?(JRUBY_VERSION)
81
+ # GC.enable/disable are noop's on Jruby
82
+ ::Protobuf.gc_pause_server_request = false
83
+ else
84
+ ::Protobuf.gc_pause_server_request = options.gc_pause_request?
85
+ end
86
+ end
87
+
88
+ # Setup the protobuf logger.
89
+ def configure_logger
90
+ debug_say('Configuring logger')
91
+ ::Protobuf::Logger.configure({ :file => options.log || STDOUT,
92
+ :level => options.debug? ? ::Logger::DEBUG : options.level })
93
+
94
+ # Debug output the server options to the log file.
95
+ ::Protobuf::Logger.debug { 'Debugging options:' }
96
+ ::Protobuf::Logger.debug { options.inspect }
97
+ end
98
+
99
+ # Re-write the $0 var to have a nice process name in ps.
100
+ def configure_process_name(app_file)
101
+ debug_say('Configuring process name')
102
+ $0 = "rpc_server --#{@runner_mode} #{options.host}:#{options.port} #{app_file}"
103
+ end
104
+
105
+ # Configure the mode of the server and the runner class.
106
+ def configure_runner_mode
107
+ debug_say('Configuring runner mode')
108
+
109
+ if multi_mode?
110
+ say('WARNING: You have provided multiple mode options. Defaulting to socket mode.', :yellow)
111
+ @runner_mode = :socket
112
+ elsif options.zmq?
113
+ @runner_mode = :zmq
114
+ elsif options.http?
115
+ @runner_mode = :http
116
+ else
117
+ case server_type = ENV["PB_SERVER_TYPE"]
118
+ when nil, /socket/i
119
+ @runner_mode = :socket
120
+ when /zmq/i
121
+ @runner_mode = :zmq
122
+ when /http/i
123
+ @runner_mode = :http
124
+ else
125
+ say "WARNING: You have provided incorrect option 'PB_SERVER_TYPE=#{server_type}'. Defaulting to socket mode.", :yellow
126
+ @runner_mode = :socket
127
+ end
128
+ end
129
+ end
130
+
131
+ # Configure signal traps.
132
+ # TODO add signal handling for hot-reloading the application.
133
+ def configure_traps
134
+ debug_say('Configuring traps')
135
+
136
+ exit_signals = [:INT, :TERM]
137
+ exit_signals << :QUIT unless defined?(JRUBY_VERSION)
138
+
139
+ exit_signals.each do |signal|
140
+ debug_say("Registering trap for exit signal #{signal}", :blue)
141
+
142
+ trap(signal) do
143
+ @exit_requested = true
144
+ shutdown_server
145
+ end
146
+ end
147
+ end
148
+
149
+ # Create the runner for the configured mode
150
+ def create_runner
151
+ debug_say("Creating #{@runner_mode} runner")
152
+ @runner = case @runner_mode
153
+ when :zmq
154
+ create_zmq_runner
155
+ when :socket
156
+ create_socket_runner
157
+ when :http
158
+ create_http_runner
159
+ else
160
+ say_and_exit("Unknown runner mode: #{@runner_mode}")
161
+ end
162
+ end
163
+
164
+ # Say something if we're in debug mode.
165
+ def debug_say(message, color = :yellow)
166
+ say(message, color) if options.debug?
167
+ end
168
+
169
+ def exit_requested?
170
+ !!@exit_requested
171
+ end
172
+
173
+ # Internal helper to determine if the modes are multi-set which is not valid.
174
+ def multi_mode?
175
+ options.zmq? && options.socket?
176
+ end
177
+
178
+ # Require the application file given, exiting if the file doesn't exist.
179
+ def require_application(app_file)
180
+ debug_say('Requiring app file')
181
+ require app_file
182
+ rescue LoadError => e
183
+ say_and_exit("Failed to load application file #{app_file}", e)
184
+ end
185
+
186
+ def runner_options
187
+ # Symbolize keys
188
+ opt = options.inject({}) { |h, (k, v)| h[k.to_sym] = v; h }
189
+
190
+ opt[:workers_only] = (!!ENV['PB_WORKERS_ONLY']) || options.workers_only
191
+
192
+ opt
193
+ end
194
+
195
+ def say_and_exit(message, exception = nil)
196
+ message = set_color(message, :red) if ::Protobuf::Logger.file == STDOUT
197
+
198
+ ::Protobuf::Logger.error { message }
199
+ if exception
200
+ $stderr.puts "[#{exception.class.name}] #{exception.message}"
201
+ $stderr.puts exception.backtrace.join("\n")
202
+
203
+ ::Protobuf::Logger.error { "[#{exception.class.name}] #{exception.message}" }
204
+ ::Protobuf::Logger.debug { exception.backtrace.join("\n") }
205
+ end
206
+
207
+ exit(1)
208
+ end
209
+
210
+ def create_socket_runner
211
+ require 'protobuf/socket'
212
+
213
+ @runner = ::Protobuf::Rpc::SocketRunner.new(runner_options)
214
+ end
215
+
216
+ def create_zmq_runner
217
+ require 'protobuf/zmq'
218
+
219
+ @runner = ::Protobuf::Rpc::ZmqRunner.new(runner_options)
220
+ end
221
+
222
+ def create_http_runner
223
+ require 'protobuf/http'
224
+
225
+ @runner = ::Protobuf::Rpc::HttpRunner.new(runner_options)
226
+ end
227
+
228
+ def shutdown_server
229
+ ::Protobuf::Logger.info { 'RPC Server shutting down...' }
230
+ @runner.try(:stop)
231
+ ::Protobuf::Rpc::ServiceDirectory.instance.stop
232
+ ::Protobuf::Logger.info { 'Shutdown complete' }
233
+ end
234
+
235
+ # Start the runner and log the relevant options.
236
+ def start_server
237
+ debug_say('Running server')
238
+
239
+ @runner.run do
240
+ ::Protobuf::Logger.info {
241
+ "pid #{::Process.pid} -- #{@runner_mode} RPC Server listening at #{options.host}:#{options.port}"
242
+ }
243
+
244
+ ::ActiveSupport::Notifications.instrument("after_server_bind")
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end