protobuffy 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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,313 @@
1
+ require 'protobuf/rpc/servers/zmq/util'
2
+ require 'protobuf/rpc/servers/zmq/worker'
3
+ require 'protobuf/rpc/servers/zmq/broker'
4
+ require 'protobuf/rpc/dynamic_discovery.pb'
5
+ require 'securerandom'
6
+ require 'thread'
7
+
8
+ module Protobuf
9
+ module Rpc
10
+ module Zmq
11
+ class Server
12
+ include ::Protobuf::Rpc::Zmq::Util
13
+
14
+ DEFAULT_OPTIONS = {
15
+ :beacon_interval => 5,
16
+ :broadcast_beacons => false,
17
+ :broadcast_busy => false,
18
+ :zmq_inproc => true,
19
+ }
20
+
21
+ attr_accessor :options, :workers
22
+ attr_reader :zmq_context
23
+
24
+ def initialize(options)
25
+ @options = DEFAULT_OPTIONS.merge(options)
26
+ @workers = []
27
+
28
+ init_zmq_context
29
+ init_beacon_socket if broadcast_beacons?
30
+ init_shutdown_pipe
31
+ rescue
32
+ teardown
33
+ raise
34
+ end
35
+
36
+ def add_worker
37
+ @total_workers = total_workers + 1
38
+ end
39
+
40
+ def all_workers_busy?
41
+ workers.all? { |thread| !!thread[:busy] }
42
+ end
43
+
44
+ def backend_port
45
+ options[:worker_port] || frontend_port + 1
46
+ end
47
+
48
+ def backend_uri
49
+ if inproc?
50
+ "inproc://#{backend_ip}:#{backend_port}"
51
+ else
52
+ "tcp://#{backend_ip}:#{backend_port}"
53
+ end
54
+ end
55
+
56
+ def beacon_interval
57
+ [options[:beacon_interval].to_i, 1].max
58
+ end
59
+
60
+ def beacon_ip
61
+ "255.255.255.255"
62
+ end
63
+
64
+ def beacon_port
65
+ unless @beacon_port
66
+ unless port = options[:beacon_port]
67
+ port = ::Protobuf::Rpc::ServiceDirectory.port
68
+ end
69
+
70
+ @beacon_port = port.to_i
71
+ end
72
+
73
+ @beacon_port
74
+ end
75
+
76
+ def beacon_uri
77
+ "udp://#{beacon_ip}:#{beacon_port}"
78
+ end
79
+
80
+ def broadcast_beacons?
81
+ !brokerless? && options[:broadcast_beacons]
82
+ end
83
+
84
+ def broadcast_flatline
85
+ flatline = ::Protobuf::Rpc::DynamicDiscovery::Beacon.new(
86
+ :beacon_type => ::Protobuf::Rpc::DynamicDiscovery::BeaconType::FLATLINE,
87
+ :server => self.to_proto
88
+ )
89
+
90
+ @beacon_socket.send(flatline.encode, 0)
91
+ end
92
+
93
+ def broadcast_heartbeat
94
+ @last_beacon = Time.now.to_i
95
+
96
+ heartbeat = ::Protobuf::Rpc::DynamicDiscovery::Beacon.new(
97
+ :beacon_type => ::Protobuf::Rpc::DynamicDiscovery::BeaconType::HEARTBEAT,
98
+ :server => self.to_proto
99
+ )
100
+
101
+ @beacon_socket.send(heartbeat.encode, 0)
102
+
103
+ log_debug { sign_message("sent heartbeat to #{beacon_uri}") }
104
+ end
105
+
106
+ def broadcast_heartbeat?
107
+ Time.now.to_i >= next_beacon && broadcast_beacons?
108
+ end
109
+
110
+ def brokerless?
111
+ !!options[:workers_only]
112
+ end
113
+
114
+ def busy_worker_count
115
+ workers.count { |thread| !!thread[:busy] }
116
+ end
117
+
118
+ def frontend_ip
119
+ @frontend_ip ||= resolve_ip(options[:host])
120
+ end
121
+ alias_method :backend_ip, :frontend_ip
122
+
123
+ def frontend_port
124
+ options[:port]
125
+ end
126
+
127
+ def frontend_uri
128
+ "tcp://#{frontend_ip}:#{frontend_port}"
129
+ end
130
+
131
+ def inproc?
132
+ !!self.options[:zmq_inproc]
133
+ end
134
+
135
+ def maintenance_timeout
136
+ next_maintenance - Time.now.to_i
137
+ end
138
+
139
+ def next_maintenance
140
+ cycles = [next_reaping]
141
+ cycles << next_beacon if broadcast_beacons?
142
+
143
+ cycles.min
144
+ end
145
+
146
+ def minimum_timeout
147
+ 0.1
148
+ end
149
+
150
+ def next_beacon
151
+ if @last_beacon.nil?
152
+ 0
153
+ else
154
+ @last_beacon + beacon_interval
155
+ end
156
+ end
157
+
158
+ def next_reaping
159
+ if @last_reaping.nil?
160
+ 0
161
+ else
162
+ @last_reaping + reaping_interval
163
+ end
164
+ end
165
+
166
+ def reap_dead_workers
167
+ @last_reaping = Time.now.to_i
168
+
169
+ @workers.keep_if do |worker|
170
+ worker.alive? or worker.join && false
171
+ end
172
+ end
173
+
174
+ def reap_dead_workers?
175
+ Time.now.to_i >= next_reaping
176
+ end
177
+
178
+ def reaping_interval
179
+ 5
180
+ end
181
+
182
+ def run
183
+ @running = true
184
+
185
+ start_broker unless brokerless?
186
+ start_missing_workers
187
+
188
+ yield if block_given? # runs on startup
189
+ wait_for_shutdown_signal
190
+ broadcast_flatline if broadcast_beacons?
191
+ Thread.pass until reap_dead_workers.empty?
192
+ @broker.join unless brokerless?
193
+ ensure
194
+ @running = false
195
+ teardown
196
+ end
197
+
198
+ def running?
199
+ !!@running
200
+ end
201
+
202
+ def start_missing_workers
203
+ missing_workers = total_workers - @workers.size
204
+
205
+ if missing_workers > 0
206
+ missing_workers.times { start_worker }
207
+ log_debug { sign_message("#{total_workers} workers started") }
208
+ end
209
+ end
210
+
211
+ def stop
212
+ @running = false
213
+ @shutdown_w.write('.')
214
+ end
215
+
216
+ def teardown
217
+ @shutdown_r.try(:close)
218
+ @shutdown_w.try(:close)
219
+ @beacon_socket.try(:close)
220
+ @zmq_context.try(:terminate)
221
+ @last_reaping = @last_beacon = @timeout = nil
222
+ end
223
+
224
+ def total_workers
225
+ @total_workers ||= [@options[:threads].to_i, 1].max
226
+ end
227
+
228
+ def timeout
229
+ if @timeout.nil?
230
+ @timeout = 0
231
+ else
232
+ @timeout = [minimum_timeout, maintenance_timeout].max
233
+ end
234
+ end
235
+
236
+ def to_proto
237
+ @proto ||= ::Protobuf::Rpc::DynamicDiscovery::Server.new(
238
+ :uuid => uuid,
239
+ :address => frontend_ip,
240
+ :port => frontend_port.to_s,
241
+ :ttl => (beacon_interval * 1.5).ceil,
242
+ :services => ::Protobuf::Rpc::Service.implemented_services
243
+ )
244
+ end
245
+
246
+ def uuid
247
+ @uuid ||= SecureRandom.uuid
248
+ end
249
+
250
+ def wait_for_shutdown_signal
251
+ loop do
252
+ break if IO.select([@shutdown_r], nil, nil, timeout)
253
+
254
+ if reap_dead_workers?
255
+ reap_dead_workers
256
+ start_missing_workers
257
+ end
258
+
259
+ if broadcast_heartbeat?
260
+ if all_workers_busy? && options[:broadcast_busy]
261
+ broadcast_flatline
262
+ else
263
+ broadcast_heartbeat
264
+ end
265
+ end
266
+
267
+ end
268
+ end
269
+
270
+ private
271
+
272
+ def init_beacon_socket
273
+ @beacon_socket = UDPSocket.new
274
+ @beacon_socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_BROADCAST, true)
275
+ @beacon_socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, true)
276
+
277
+ if defined?(::Socket::SO_REUSEPORT)
278
+ @beacon_socket.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEPORT, true)
279
+ end
280
+
281
+ @beacon_socket.bind(frontend_ip, beacon_port)
282
+ @beacon_socket.connect(beacon_ip, beacon_port)
283
+ end
284
+
285
+ def init_shutdown_pipe
286
+ @shutdown_r, @shutdown_w = IO.pipe
287
+ end
288
+
289
+ def init_zmq_context
290
+ @zmq_context = ZMQ::Context.new
291
+ end
292
+
293
+ def start_broker
294
+ @broker = Thread.new(self) do |server|
295
+ ::Protobuf::Rpc::Zmq::Broker.new(server).run
296
+ end
297
+ end
298
+
299
+ def start_worker
300
+ @workers << Thread.new(self) do |server|
301
+ begin
302
+ ::Protobuf::Rpc::Zmq::Worker.new(server).run
303
+ rescue => e
304
+ message = "Worker failed: #{e.inspect}\n #{e.backtrace.join($/)}"
305
+ $stderr.puts(message)
306
+ log_error { message }
307
+ end
308
+ end
309
+ end
310
+ end
311
+ end
312
+ end
313
+ end
@@ -0,0 +1,47 @@
1
+ require 'resolv'
2
+
3
+ module Protobuf
4
+ module Rpc
5
+ module Zmq
6
+
7
+ ADDRESS_MATCH = /\A\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\z/.freeze
8
+ WORKER_READY_MESSAGE = "\1"
9
+ CHECK_AVAILABLE_MESSAGE = "\3"
10
+ NO_WORKERS_AVAILABLE = "\4"
11
+ WORKERS_AVAILABLE = "\5"
12
+
13
+ module Util
14
+ include ::Protobuf::Logger::LogMethods
15
+
16
+ def self.included(base)
17
+ base.extend(::Protobuf::Rpc::Zmq::Util)
18
+ end
19
+
20
+ def zmq_error_check(return_code, source = nil)
21
+ unless ::ZMQ::Util.resultcode_ok?(return_code)
22
+ raise <<-ERROR
23
+ Last ZMQ API call #{source ? "to #{source}" : ""} failed with "#{::ZMQ::Util.error_string}".
24
+
25
+ #{caller(1).join($/)}
26
+ ERROR
27
+ end
28
+ end
29
+
30
+ def log_signature
31
+ unless @_log_signature
32
+ name = (self.class == Class ? self.name : self.class.name)
33
+ @_log_signature = "[server-#{name}-#{object_id}]"
34
+ end
35
+
36
+ @_log_signature
37
+ end
38
+
39
+ def resolve_ip(hostname)
40
+ ::Resolv.getaddresses(hostname).detect do |address|
41
+ address =~ ADDRESS_MATCH
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,105 @@
1
+ require 'protobuf/rpc/server'
2
+ require 'protobuf/rpc/servers/zmq/util'
3
+ require 'thread'
4
+
5
+ module Protobuf
6
+ module Rpc
7
+ module Zmq
8
+ class Worker
9
+ include ::Protobuf::Rpc::Server
10
+ include ::Protobuf::Rpc::Zmq::Util
11
+
12
+ ##
13
+ # Constructor
14
+ #
15
+ def initialize(server)
16
+ @server = server
17
+
18
+ init_zmq_context
19
+ init_backend_socket
20
+ rescue
21
+ teardown
22
+ raise
23
+ end
24
+
25
+ ##
26
+ # Instance Methods
27
+ #
28
+ def process_request
29
+ client_address, _, data = read_from_backend
30
+ return unless data
31
+
32
+ gc_pause do
33
+ encoded_response = handle_request(data)
34
+ write_to_backend([client_address, "", encoded_response])
35
+ end
36
+ end
37
+
38
+ def run
39
+ poller = ::ZMQ::Poller.new
40
+ poller.register_readable(@backend_socket)
41
+ poller.register_readable(@shutdown_socket)
42
+
43
+ # Send request to broker telling it we are ready
44
+ write_to_backend([::Protobuf::Rpc::Zmq::WORKER_READY_MESSAGE])
45
+
46
+ loop do
47
+ rc = poller.poll(500)
48
+
49
+ # The server was shutdown and no requests are pending
50
+ break if rc == 0 && !running?
51
+
52
+ # Something went wrong
53
+ break if rc == -1
54
+
55
+ if rc > 0
56
+ ::Thread.current[:busy] = true
57
+ process_request
58
+ ::Thread.current[:busy] = false
59
+ end
60
+ end
61
+ ensure
62
+ teardown
63
+ end
64
+
65
+ def running?
66
+ @server.running?
67
+ end
68
+
69
+ private
70
+
71
+ def init_zmq_context
72
+ if inproc?
73
+ @zmq_context = @server.zmq_context
74
+ else
75
+ @zmq_context = ZMQ::Context.new
76
+ end
77
+ end
78
+
79
+ def init_backend_socket
80
+ @backend_socket = @zmq_context.socket(ZMQ::REQ)
81
+ zmq_error_check(@backend_socket.connect(@server.backend_uri))
82
+ end
83
+
84
+ def inproc?
85
+ !!@server.try(:inproc?)
86
+ end
87
+
88
+ def read_from_backend
89
+ frames = []
90
+ zmq_error_check(@backend_socket.recv_strings(frames))
91
+ frames
92
+ end
93
+
94
+ def teardown
95
+ @backend_socket.try(:close)
96
+ @zmq_context.try(:terminate)
97
+ end
98
+
99
+ def write_to_backend(frames)
100
+ zmq_error_check(@backend_socket.send_strings(frames))
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end