protobuf 2.2.5-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (256) hide show
  1. data/.gitignore +17 -0
  2. data/.travis.yml +9 -0
  3. data/.yardopts +5 -0
  4. data/Gemfile +3 -0
  5. data/README.md +316 -0
  6. data/Rakefile +29 -0
  7. data/UPGRADING.md +60 -0
  8. data/bin/rpc_server +5 -0
  9. data/bin/rprotoc +62 -0
  10. data/examples/addressbook.pb.rb +55 -0
  11. data/examples/addressbook.proto +24 -0
  12. data/examples/reading_a_message.rb +32 -0
  13. data/examples/writing_a_message.rb +46 -0
  14. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/code_generator.h +142 -0
  15. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/command_line_interface.h +318 -0
  16. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_enum.h +99 -0
  17. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_enum_field.h +103 -0
  18. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_extension.h +85 -0
  19. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_field.h +167 -0
  20. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_file.h +98 -0
  21. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_generator.h +72 -0
  22. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_helpers.h +159 -0
  23. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_message.h +170 -0
  24. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_message_field.h +102 -0
  25. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_primitive_field.h +103 -0
  26. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_service.h +118 -0
  27. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_string_field.h +104 -0
  28. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/cpp/cpp_test_bad_identifiers.pb.h +2721 -0
  29. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/importer.h +303 -0
  30. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_enum.h +84 -0
  31. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_enum_field.h +121 -0
  32. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_extension.h +77 -0
  33. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_field.h +108 -0
  34. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_file.h +101 -0
  35. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_generator.h +72 -0
  36. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_helpers.h +213 -0
  37. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_message.h +109 -0
  38. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_message_field.h +134 -0
  39. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_primitive_field.h +121 -0
  40. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_service.h +113 -0
  41. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/java/java_string_field.h +120 -0
  42. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/mock_code_generator.h +113 -0
  43. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/package_info.h +64 -0
  44. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/parser.h +434 -0
  45. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/plugin.h +73 -0
  46. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/plugin.pb.h +790 -0
  47. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/python/python_generator.h +156 -0
  48. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/subprocess.h +108 -0
  49. data/ext/protobuf-2.4.1/src/google/protobuf/compiler/zip_writer.h +93 -0
  50. data/ext/protobuf-2.4.1/src/google/protobuf/descriptor.h +1367 -0
  51. data/ext/protobuf-2.4.1/src/google/protobuf/descriptor.pb.h +5223 -0
  52. data/ext/protobuf-2.4.1/src/google/protobuf/descriptor_database.h +366 -0
  53. data/ext/protobuf-2.4.1/src/google/protobuf/dynamic_message.h +136 -0
  54. data/ext/protobuf-2.4.1/src/google/protobuf/extension_set.h +904 -0
  55. data/ext/protobuf-2.4.1/src/google/protobuf/generated_message_reflection.h +424 -0
  56. data/ext/protobuf-2.4.1/src/google/protobuf/generated_message_util.h +82 -0
  57. data/ext/protobuf-2.4.1/src/google/protobuf/io/coded_stream.h +1102 -0
  58. data/ext/protobuf-2.4.1/src/google/protobuf/io/coded_stream_inl.h +64 -0
  59. data/ext/protobuf-2.4.1/src/google/protobuf/io/gzip_stream.h +207 -0
  60. data/ext/protobuf-2.4.1/src/google/protobuf/io/package_info.h +54 -0
  61. data/ext/protobuf-2.4.1/src/google/protobuf/io/printer.h +136 -0
  62. data/ext/protobuf-2.4.1/src/google/protobuf/io/tokenizer.h +313 -0
  63. data/ext/protobuf-2.4.1/src/google/protobuf/io/zero_copy_stream.h +238 -0
  64. data/ext/protobuf-2.4.1/src/google/protobuf/io/zero_copy_stream_impl.h +357 -0
  65. data/ext/protobuf-2.4.1/src/google/protobuf/io/zero_copy_stream_impl_lite.h +340 -0
  66. data/ext/protobuf-2.4.1/src/google/protobuf/message.h +692 -0
  67. data/ext/protobuf-2.4.1/src/google/protobuf/message_lite.h +239 -0
  68. data/ext/protobuf-2.4.1/src/google/protobuf/package_info.h +64 -0
  69. data/ext/protobuf-2.4.1/src/google/protobuf/reflection_ops.h +80 -0
  70. data/ext/protobuf-2.4.1/src/google/protobuf/repeated_field.h +1295 -0
  71. data/ext/protobuf-2.4.1/src/google/protobuf/service.h +291 -0
  72. data/ext/protobuf-2.4.1/src/google/protobuf/stubs/common.h +1211 -0
  73. data/ext/protobuf-2.4.1/src/google/protobuf/stubs/hash.h +220 -0
  74. data/ext/protobuf-2.4.1/src/google/protobuf/stubs/map-util.h +119 -0
  75. data/ext/protobuf-2.4.1/src/google/protobuf/stubs/once.h +123 -0
  76. data/ext/protobuf-2.4.1/src/google/protobuf/stubs/stl_util-inl.h +121 -0
  77. data/ext/protobuf-2.4.1/src/google/protobuf/stubs/strutil.h +457 -0
  78. data/ext/protobuf-2.4.1/src/google/protobuf/stubs/substitute.h +170 -0
  79. data/ext/protobuf-2.4.1/src/google/protobuf/test_util.h +174 -0
  80. data/ext/protobuf-2.4.1/src/google/protobuf/test_util_lite.h +101 -0
  81. data/ext/protobuf-2.4.1/src/google/protobuf/testing/file.h +83 -0
  82. data/ext/protobuf-2.4.1/src/google/protobuf/testing/googletest.h +98 -0
  83. data/ext/protobuf-2.4.1/src/google/protobuf/text_format.h +285 -0
  84. data/ext/protobuf-2.4.1/src/google/protobuf/unittest.pb.h +11915 -0
  85. data/ext/protobuf-2.4.1/src/google/protobuf/unittest_custom_options.pb.h +2895 -0
  86. data/ext/protobuf-2.4.1/src/google/protobuf/unittest_embed_optimize_for.pb.h +211 -0
  87. data/ext/protobuf-2.4.1/src/google/protobuf/unittest_empty.pb.h +56 -0
  88. data/ext/protobuf-2.4.1/src/google/protobuf/unittest_import.pb.h +188 -0
  89. data/ext/protobuf-2.4.1/src/google/protobuf/unittest_import_lite.pb.h +151 -0
  90. data/ext/protobuf-2.4.1/src/google/protobuf/unittest_lite.pb.h +4752 -0
  91. data/ext/protobuf-2.4.1/src/google/protobuf/unittest_lite_imports_nonlite.pb.h +150 -0
  92. data/ext/protobuf-2.4.1/src/google/protobuf/unittest_mset.pb.h +816 -0
  93. data/ext/protobuf-2.4.1/src/google/protobuf/unittest_no_generic_services.pb.h +197 -0
  94. data/ext/protobuf-2.4.1/src/google/protobuf/unittest_optimize_for.pb.h +403 -0
  95. data/ext/protobuf-2.4.1/src/google/protobuf/unknown_field_set.h +268 -0
  96. data/ext/protobuf-2.4.1/src/google/protobuf/wire_format.h +304 -0
  97. data/ext/protobuf-2.4.1/src/google/protobuf/wire_format_lite.h +620 -0
  98. data/ext/protobuf-2.4.1/src/google/protobuf/wire_format_lite_inl.h +774 -0
  99. data/ext/ruby_generator/Makefile +10 -0
  100. data/ext/ruby_generator/RubyGenerator.cpp +450 -0
  101. data/ext/ruby_generator/RubyGenerator.h +199 -0
  102. data/ext/ruby_generator/extconf.rb +36 -0
  103. data/ext/ruby_generator/protoc-ruby +0 -0
  104. data/lib/protobuf/cli.rb +188 -0
  105. data/lib/protobuf/enum.rb +58 -0
  106. data/lib/protobuf/enum_value.rb +59 -0
  107. data/lib/protobuf/evented.rb +22 -0
  108. data/lib/protobuf/exceptions.rb +11 -0
  109. data/lib/protobuf/ext/eventmachine.rb +14 -0
  110. data/lib/protobuf/field/base_field.rb +240 -0
  111. data/lib/protobuf/field/bool_field.rb +36 -0
  112. data/lib/protobuf/field/bytes_field.rb +38 -0
  113. data/lib/protobuf/field/double_field.rb +19 -0
  114. data/lib/protobuf/field/enum_field.rb +50 -0
  115. data/lib/protobuf/field/extension_fields.rb +32 -0
  116. data/lib/protobuf/field/field_array.rb +65 -0
  117. data/lib/protobuf/field/fixed32_field.rb +19 -0
  118. data/lib/protobuf/field/fixed64_field.rb +22 -0
  119. data/lib/protobuf/field/float_field.rb +31 -0
  120. data/lib/protobuf/field/int32_field.rb +12 -0
  121. data/lib/protobuf/field/int64_field.rb +12 -0
  122. data/lib/protobuf/field/integer_field.rb +19 -0
  123. data/lib/protobuf/field/message_field.rb +53 -0
  124. data/lib/protobuf/field/sfixed32_field.rb +21 -0
  125. data/lib/protobuf/field/sfixed64_field.rb +24 -0
  126. data/lib/protobuf/field/signed_integer_field.rb +23 -0
  127. data/lib/protobuf/field/sint32_field.rb +12 -0
  128. data/lib/protobuf/field/sint64_field.rb +12 -0
  129. data/lib/protobuf/field/string_field.rb +14 -0
  130. data/lib/protobuf/field/uint32_field.rb +12 -0
  131. data/lib/protobuf/field/uint64_field.rb +12 -0
  132. data/lib/protobuf/field/varint_field.rb +61 -0
  133. data/lib/protobuf/field.rb +57 -0
  134. data/lib/protobuf/logger.rb +86 -0
  135. data/lib/protobuf/message/decoder.rb +83 -0
  136. data/lib/protobuf/message/encoder.rb +48 -0
  137. data/lib/protobuf/message/extend.rb +8 -0
  138. data/lib/protobuf/message/message.rb +1 -0
  139. data/lib/protobuf/message.rb +320 -0
  140. data/lib/protobuf/rpc/buffer.rb +79 -0
  141. data/lib/protobuf/rpc/client.rb +166 -0
  142. data/lib/protobuf/rpc/connector.rb +19 -0
  143. data/lib/protobuf/rpc/connectors/base.rb +38 -0
  144. data/lib/protobuf/rpc/connectors/common.rb +156 -0
  145. data/lib/protobuf/rpc/connectors/em_client.rb +84 -0
  146. data/lib/protobuf/rpc/connectors/eventmachine.rb +87 -0
  147. data/lib/protobuf/rpc/connectors/socket.rb +73 -0
  148. data/lib/protobuf/rpc/connectors/zmq.rb +69 -0
  149. data/lib/protobuf/rpc/error/client_error.rb +31 -0
  150. data/lib/protobuf/rpc/error/server_error.rb +43 -0
  151. data/lib/protobuf/rpc/error.rb +25 -0
  152. data/lib/protobuf/rpc/rpc.pb.rb +118 -0
  153. data/lib/protobuf/rpc/server.rb +89 -0
  154. data/lib/protobuf/rpc/servers/evented/server.rb +41 -0
  155. data/lib/protobuf/rpc/servers/evented_runner.rb +21 -0
  156. data/lib/protobuf/rpc/servers/socket/server.rb +111 -0
  157. data/lib/protobuf/rpc/servers/socket/worker.rb +66 -0
  158. data/lib/protobuf/rpc/servers/socket_runner.rb +27 -0
  159. data/lib/protobuf/rpc/servers/zmq/broker.rb +87 -0
  160. data/lib/protobuf/rpc/servers/zmq/server.rb +50 -0
  161. data/lib/protobuf/rpc/servers/zmq/util.rb +27 -0
  162. data/lib/protobuf/rpc/servers/zmq/worker.rb +60 -0
  163. data/lib/protobuf/rpc/servers/zmq_runner.rb +25 -0
  164. data/lib/protobuf/rpc/service.rb +173 -0
  165. data/lib/protobuf/rpc/service_dispatcher.rb +130 -0
  166. data/lib/protobuf/rpc/service_filters.rb +267 -0
  167. data/lib/protobuf/rpc/stat.rb +83 -0
  168. data/lib/protobuf/socket.rb +22 -0
  169. data/lib/protobuf/version.rb +4 -0
  170. data/lib/protobuf/wire_type.rb +10 -0
  171. data/lib/protobuf/zmq.rb +21 -0
  172. data/lib/protobuf.rb +86 -0
  173. data/proto/rpc.pb.rb +48 -0
  174. data/proto/rpc.proto +73 -0
  175. data/protobuf.gemspec +44 -0
  176. data/spec/benchmark/tasks.rb +179 -0
  177. data/spec/functional/embedded_service_spec.rb +7 -0
  178. data/spec/functional/evented_server_spec.rb +64 -0
  179. data/spec/functional/socket_server_spec.rb +58 -0
  180. data/spec/functional/zmq_server_spec.rb +58 -0
  181. data/spec/lib/protobuf/cli_spec.rb +212 -0
  182. data/spec/lib/protobuf/enum_spec.rb +98 -0
  183. data/spec/lib/protobuf/enum_value_spec.rb +15 -0
  184. data/spec/lib/protobuf/logger_spec.rb +131 -0
  185. data/spec/lib/protobuf/message/encoder_spec.rb +19 -0
  186. data/spec/lib/protobuf/message_spec.rb +209 -0
  187. data/spec/lib/protobuf/rpc/client_spec.rb +158 -0
  188. data/spec/lib/protobuf/rpc/connector_spec.rb +32 -0
  189. data/spec/lib/protobuf/rpc/connectors/base_spec.rb +50 -0
  190. data/spec/lib/protobuf/rpc/connectors/common_spec.rb +128 -0
  191. data/spec/lib/protobuf/rpc/connectors/socket_spec.rb +36 -0
  192. data/spec/lib/protobuf/rpc/connectors/zmq_spec.rb +22 -0
  193. data/spec/lib/protobuf/rpc/servers/evented_server_spec.rb +18 -0
  194. data/spec/lib/protobuf/rpc/servers/socket_server_spec.rb +43 -0
  195. data/spec/lib/protobuf/rpc/servers/zmq/broker_spec.rb +35 -0
  196. data/spec/lib/protobuf/rpc/servers/zmq/server_spec.rb +41 -0
  197. data/spec/lib/protobuf/rpc/servers/zmq/util_spec.rb +45 -0
  198. data/spec/lib/protobuf/rpc/servers/zmq/worker_spec.rb +44 -0
  199. data/spec/lib/protobuf/rpc/service_dispatcher_spec.rb +116 -0
  200. data/spec/lib/protobuf/rpc/service_filters_spec.rb +451 -0
  201. data/spec/lib/protobuf/rpc/service_spec.rb +165 -0
  202. data/spec/lib/protobuf_spec.rb +62 -0
  203. data/spec/spec_helper.rb +51 -0
  204. data/spec/support/all.rb +6 -0
  205. data/spec/support/server.rb +101 -0
  206. data/spec/support/test/enum.pb.rb +34 -0
  207. data/spec/support/test/enum.proto +12 -0
  208. data/spec/support/test/resource.pb.rb +58 -0
  209. data/spec/support/test/resource.proto +31 -0
  210. data/spec/support/test/resource_service.rb +14 -0
  211. data/spec/support/test_app_file.rb +2 -0
  212. data/spec/support/tolerance_matcher.rb +40 -0
  213. data/test/data/data.bin +3 -0
  214. data/test/data/data_source.py +14 -0
  215. data/test/data/types.bin +0 -0
  216. data/test/data/types_source.py +22 -0
  217. data/test/data/unk.png +0 -0
  218. data/test/proto/addressbook.pb.rb +66 -0
  219. data/test/proto/addressbook.proto +33 -0
  220. data/test/proto/addressbook_base.pb.rb +58 -0
  221. data/test/proto/addressbook_base.proto +26 -0
  222. data/test/proto/addressbook_ext.pb.rb +20 -0
  223. data/test/proto/addressbook_ext.proto +6 -0
  224. data/test/proto/collision.pb.rb +17 -0
  225. data/test/proto/collision.proto +5 -0
  226. data/test/proto/ext_collision.pb.rb +24 -0
  227. data/test/proto/ext_collision.proto +8 -0
  228. data/test/proto/ext_range.pb.rb +22 -0
  229. data/test/proto/ext_range.proto +7 -0
  230. data/test/proto/float_default.proto +10 -0
  231. data/test/proto/lowercase.pb.rb +30 -0
  232. data/test/proto/lowercase.proto +9 -0
  233. data/test/proto/merge.pb.rb +39 -0
  234. data/test/proto/merge.proto +15 -0
  235. data/test/proto/nested.pb.rb +30 -0
  236. data/test/proto/nested.proto +9 -0
  237. data/test/proto/optional_field.pb.rb +35 -0
  238. data/test/proto/optional_field.proto +12 -0
  239. data/test/proto/packed.pb.rb +22 -0
  240. data/test/proto/packed.proto +6 -0
  241. data/test/proto/rpc.proto +6 -0
  242. data/test/proto/types.pb.rb +84 -0
  243. data/test/proto/types.proto +37 -0
  244. data/test/test_addressbook.rb +56 -0
  245. data/test/test_enum_value.rb +41 -0
  246. data/test/test_extension.rb +36 -0
  247. data/test/test_lowercase.rb +11 -0
  248. data/test/test_message.rb +128 -0
  249. data/test/test_optional_field.rb +103 -0
  250. data/test/test_packed_field.rb +40 -0
  251. data/test/test_parse.rb +15 -0
  252. data/test/test_repeated_types.rb +132 -0
  253. data/test/test_serialize.rb +61 -0
  254. data/test/test_standard_message.rb +96 -0
  255. data/test/test_types.rb +226 -0
  256. metadata +461 -0
@@ -0,0 +1,60 @@
1
+ require 'protobuf/rpc/server'
2
+ require 'protobuf/rpc/servers/zmq/util'
3
+ module Protobuf
4
+ module Rpc
5
+ module Zmq
6
+
7
+ class Worker
8
+ include ::Protobuf::Rpc::Server
9
+ include ::Protobuf::Rpc::Zmq::Util
10
+
11
+ ##
12
+ # Constructor
13
+ #
14
+ def initialize(options = {})
15
+ host = options[:host]
16
+ port = options[:port]
17
+
18
+ @zmq_context = ::ZMQ::Context.new
19
+ @socket = @zmq_context.socket(::ZMQ::REP)
20
+ zmq_error_check(@socket.connect("tcp://#{resolve_ip(host)}:#{port}"))
21
+
22
+ @poller = ::ZMQ::Poller.new
23
+ @poller.register(@socket, ::ZMQ::POLLIN)
24
+ end
25
+
26
+ ##
27
+ # Instance Methods
28
+ #
29
+ def handle_request(socket)
30
+ @request_data = ''
31
+ zmq_error_check(socket.recv_string(@request_data))
32
+ log_debug { sign_message("handling request") } if !@request_data.nil?
33
+ end
34
+
35
+ def run
36
+ while ::Protobuf::Rpc::Zmq::Server.running? do
37
+ # poll for 1_000 milliseconds then continue looping
38
+ # This lets us see whether we need to die
39
+ @poller.poll(1_000)
40
+ @poller.readables.each do |socket|
41
+ initialize_request!
42
+ handle_request(socket)
43
+ handle_client unless @request_data.nil?
44
+ end
45
+ end
46
+ ensure
47
+ @socket.close
48
+ @zmq_context.terminate
49
+ end
50
+
51
+ def send_data
52
+ response_data = @response.is_a?(::Protobuf::Message) ? @response.serialize_to_string : @response.to_s
53
+ @stats.response_size = response_data.size
54
+ zmq_error_check(@socket.send_string(response_data))
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,25 @@
1
+ module Protobuf
2
+ module Rpc
3
+ class ZmqRunner
4
+
5
+ def self.stop
6
+ Protobuf::Rpc::Zmq::Server.stop
7
+ end
8
+
9
+ def self.run(server)
10
+ server_config = case
11
+ when server.is_a?(OpenStruct) then
12
+ server.marshal_dump
13
+ when server.respond_to?(:to_hash) then
14
+ server.to_hash
15
+ else
16
+ raise "Cannot parser Zmq Server - server options"
17
+ end
18
+
19
+ yield if block_given?
20
+ Protobuf::Rpc::Zmq::Server.run(server_config)
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,173 @@
1
+ require 'protobuf/logger'
2
+ require 'protobuf/rpc/client'
3
+ require 'protobuf/rpc/error'
4
+ require 'protobuf/rpc/service_filters'
5
+
6
+ module Protobuf
7
+ module Rpc
8
+
9
+ # Object to encapsulate the request/response types for a given service method
10
+ #
11
+ RpcMethod = Struct.new("RpcMethod", :method, :request_type, :response_type)
12
+
13
+ class Service
14
+ include Protobuf::Rpc::ServiceFilters
15
+ include Protobuf::Logger::LogMethods
16
+
17
+
18
+ attr_reader :response, :rpc
19
+
20
+ DEFAULT_HOST = '127.0.0.1'.freeze
21
+ DEFAULT_PORT = 9399
22
+
23
+ ##
24
+ # Class Methods
25
+ #
26
+
27
+ # Create a new client for the given service.
28
+ # See Client#initialize and ClientConnection::DEFAULT_OPTIONS
29
+ # for all available options.
30
+ #
31
+ def self.client(options = {})
32
+ ::Protobuf::Rpc::Client.new({ :service => self,
33
+ :host => host,
34
+ :port => port }.merge(options))
35
+ end
36
+
37
+ # Allows service-level configuration of location.
38
+ # Useful for system-startup configuration of a service
39
+ # so that any Clients using the Service.client sugar
40
+ # will not have to configure the location each time.
41
+ #
42
+ def self.configure(config = {})
43
+ self.host = config[:host] if config.key?(:host)
44
+ self.port = config[:port] if config.key?(:port)
45
+ end
46
+
47
+ # The host location of the service.
48
+ #
49
+ def self.host
50
+ @_host ||= DEFAULT_HOST
51
+ end
52
+
53
+ # The host location setter.
54
+ #
55
+ def self.host=(new_host)
56
+ @_host = new_host
57
+ end
58
+
59
+ # Shorthand call to configure, passing a string formatted as hostname:port
60
+ # e.g. 127.0.0.1:9933
61
+ # e.g. localhost:0
62
+ #
63
+ def self.located_at(location)
64
+ return if location.nil? || location.downcase.strip !~ /.+:\d+/
65
+ host, port = location.downcase.strip.split ':'
66
+ configure(:host => host, :port => port.to_i)
67
+ end
68
+
69
+ # The port of the service on the destination server.
70
+ #
71
+ def self.port
72
+ @_port ||= DEFAULT_PORT
73
+ end
74
+
75
+ # The port location setter.
76
+ #
77
+ def self.port=(new_port)
78
+ @_port = new_port
79
+ end
80
+
81
+ # Define an rpc method with the given request and response types.
82
+ # This methods is only used by the generated service definitions
83
+ # and not useful for user code.
84
+ #
85
+ def self.rpc(method, request_type, response_type)
86
+ rpcs[method] = RpcMethod.new(method, request_type, response_type)
87
+ end
88
+
89
+ # Hash containing the set of methods defined via `rpc`.
90
+ #
91
+ def self.rpcs
92
+ @_rpcs ||= {}
93
+ end
94
+
95
+ # Check if the given method name is a known rpc endpoint.
96
+ #
97
+ def self.rpc_method?(name)
98
+ rpcs.key?(name)
99
+ end
100
+
101
+
102
+ ##
103
+ # Instance Methods
104
+ #
105
+
106
+ # Initialize a service with the rpc endpoint name and the bytes
107
+ # for the request.
108
+ def initialize(rpc, request_bytes)
109
+ @rpc = rpc
110
+ @request_bytes = request_bytes
111
+ end
112
+
113
+ # Register a failure callback for use when rpc_failed is invoked.
114
+ #
115
+ def on_rpc_failed(callable)
116
+ @rpc_failed_callback ||= callable
117
+ end
118
+
119
+ # Response object for this rpc cycle. Not assignable.
120
+ #
121
+ def response
122
+ @_response ||= rpcs[@rpc].response_type.new
123
+ end
124
+
125
+ # Convenience method to get back to class method.
126
+ #
127
+ def rpc_method?(name)
128
+ self.class.rpc_method?(name)
129
+ end
130
+
131
+ # Convenience method to get back to class rpcs hash.
132
+ #
133
+ def rpcs
134
+ self.class.rpcs
135
+ end
136
+
137
+ # Get a callable object that will be used by the dispatcher
138
+ # to invoke the specified rpc method. Facilitates callback dispatch.
139
+ # The returned lambda is expected to be called at a later time (which
140
+ # is why we wrap the method call).
141
+ #
142
+ def callable_rpc_method(method_name)
143
+ lambda { run_filters(method_name) }
144
+ end
145
+
146
+ private
147
+
148
+ # Request object for this rpc cycle. Not assignable.
149
+ #
150
+ def request
151
+ @_request ||= rpcs[@rpc].request_type.new.parse_from_string(@request_bytes)
152
+ rescue => e
153
+ raise BadRequestProto, "Unable to parse request: #{e.message}"
154
+ end
155
+
156
+ # Sugar to make an rpc method feel like a controller method.
157
+ # If this method is not called, the response will be the memoized
158
+ # object returned by the response reader.
159
+ #
160
+ def respond_with(candidate)
161
+ @_response = candidate
162
+ end
163
+ alias_method :return_from_whence_you_came, :respond_with
164
+
165
+ # Automatically fail a service method.
166
+ #
167
+ def rpc_failed(message)
168
+ @rpc_failed_callback.call(message)
169
+ end
170
+
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,130 @@
1
+ require 'protobuf/logger'
2
+
3
+ module Protobuf
4
+ module Rpc
5
+ class ServiceDispatcher
6
+
7
+ include ::Protobuf::Logger::LogMethods
8
+
9
+ attr_accessor :service, :service_klass, :callable_method, :outer_request
10
+ attr_accessor :definition, :response, :error
11
+
12
+ def initialize(wrapper_request)
13
+ self.error = nil
14
+ self.outer_request = wrapper_request
15
+
16
+ init_service
17
+ init_method if service_klass.present?
18
+ register_rpc_failed if service.present?
19
+ end
20
+
21
+ # Call the given service method. If we get to this point and an error
22
+ # has already occurred, do not invoke the method and simply respond.
23
+ #
24
+ def invoke!
25
+ unless error?
26
+ callable_method.call
27
+ validate_response
28
+ end
29
+
30
+ return error || response
31
+ end
32
+
33
+ # We're successful if the error is not populated.
34
+ #
35
+ def success?
36
+ error.nil?
37
+ end
38
+
39
+ # We're in error if the error is populated.
40
+ #
41
+ def error?
42
+ ! success?
43
+ end
44
+
45
+ private
46
+
47
+ def assign_error(error_klass, message)
48
+ self.error = error_klass.new(message)
49
+ end
50
+
51
+ # Prod the object to see if we can produce a proto object as a response
52
+ # candidate. Either way, return the candidate for validation.
53
+ def coerced_response
54
+ candidate = service.response
55
+
56
+ case
57
+ when candidate.is_a?(::Protobuf::Message) then
58
+ # no-op
59
+ when candidate.respond_to?(:to_proto) then
60
+ candidate = candidate.to_proto
61
+ when candidate.respond_to?(:to_proto_hash) then
62
+ candidate = definition.response_type.new(candidate.to_proto_hash)
63
+ when candidate.respond_to?(:to_hash) then
64
+ candidate = definition.response_type.new(candidate.to_hash)
65
+ end
66
+
67
+ candidate
68
+ end
69
+
70
+ # Get the method for the current request.
71
+ #
72
+ def init_method
73
+ method_name = outer_request.method_name.underscore.to_sym
74
+ if service_klass.rpc_method?(method_name)
75
+ self.service = service_klass.new(method_name, outer_request.request_proto)
76
+ self.callable_method = service.callable_rpc_method(method_name)
77
+ self.definition = service.rpcs[method_name]
78
+ else
79
+ assign_error(MethodNotFound, "#{service.class.name}##{method_name} is not a defined rpc method.")
80
+ end
81
+ rescue NameError => e
82
+ # FIXME I think this is no longer applicable since the method extract
83
+ # is now wrapped in a lambda (@see Service#callable_rpc_method).
84
+ log_exception(e)
85
+ assign_error(MethodNotFound, "#{service.class.name}##{method_name} is not implemented.")
86
+ end
87
+
88
+ # Constantize the service for this request. Initialization of the service
89
+ # happens when we verify that the method is callable for this service.
90
+ #
91
+ def init_service
92
+ self.service_klass = outer_request.service_name.constantize
93
+ rescue NameError => e
94
+ log_exception(e)
95
+ assign_error(ServiceNotFound, "Service class #{outer_request.service_name} is not defined.")
96
+ end
97
+
98
+ # Make sure we get rpc errors back.
99
+ #
100
+ def register_rpc_failed
101
+ service.on_rpc_failed(method(:rpc_failed_callback))
102
+ end
103
+
104
+ # Receive the failure message from the service. This method is registered
105
+ # as the callable to the service when an `rpc_failed` call is invoked.
106
+ #
107
+ def rpc_failed_callback(message)
108
+ assign_error(RpcFailed, (message.respond_to?(:message) ? message.message : message))
109
+ log_error { sign_message("RPC Failed: #{error.message}") }
110
+ end
111
+
112
+ # Ensure that the response candidate we've been given is of the type
113
+ # we expect so that deserialization on the client side works.
114
+ #
115
+ def validate_response
116
+ candidate = coerced_response
117
+ expected = definition.response_type
118
+ actual = candidate.class
119
+
120
+ if expected == actual
121
+ self.response = candidate
122
+ else
123
+ assign_error(BadResponseProto, "Response proto changed from #{expected.name} to #{actual.name}")
124
+ end
125
+ end
126
+
127
+ end
128
+ end
129
+ end
130
+
@@ -0,0 +1,267 @@
1
+ module Protobuf
2
+ module Rpc
3
+ module ServiceFilters
4
+
5
+ def self.included(other)
6
+ other.class_eval do
7
+ extend Protobuf::Rpc::ServiceFilters::ClassMethods
8
+ include Protobuf::Rpc::ServiceFilters::InstanceMethods
9
+ end
10
+ end
11
+
12
+ module ClassMethods
13
+
14
+ [:after, :around, :before].each do |type|
15
+ # Setter DSL method for given filter types.
16
+ #
17
+ define_method "#{type}_filter" do |*args|
18
+ set_filters(type, *args)
19
+ end
20
+ end
21
+
22
+ # Filters hash keyed based on filter type (e.g. :before, :after, :around),
23
+ # whose values are Sets.
24
+ #
25
+ def filters
26
+ @filters ||= Hash.new { |h,k| h[k] = [] }
27
+ end
28
+
29
+ # Filters hash keyed based on filter type (e.g. :before, :after, :around),
30
+ # whose values are Sets.
31
+ #
32
+ def rescue_filters
33
+ @rescue_filters ||= {}
34
+ end
35
+
36
+ def rescue_from(*ex_klasses, &block)
37
+ options = ex_klasses.last.is_a?(Hash) ? ex_klasses.pop : {}
38
+ callable = options.delete(:with) { block }
39
+ raise ArgumentError, 'Option :with missing from rescue_from options' if callable.nil?
40
+ ex_klasses.each { |ex_klass| rescue_filters[ex_klass] = callable }
41
+ end
42
+
43
+ private
44
+
45
+ def define_filter(type, filter, options = {})
46
+ return if filter_defined?(type, filter)
47
+ filters[type] << options.merge({ :callable => filter })
48
+ remember_filter(type, filter)
49
+ end
50
+
51
+ def defined_filters
52
+ @defined_filters ||= Hash.new { |h,k| h[k] = Set.new }
53
+ end
54
+
55
+ # Check to see if the filter has been defined.
56
+ #
57
+ def filter_defined?(type, filter)
58
+ defined_filters[type].include?(filter)
59
+ end
60
+
61
+ # Remember that we stored the filter.
62
+ #
63
+ def remember_filter(type, filter)
64
+ defined_filters[type] << filter
65
+ end
66
+
67
+ # Takes a list of actually (or potentially) callable objects.
68
+ # TODO add support for if/unless
69
+ # TODO add support for only/except sub-filters
70
+ #
71
+ def set_filters(type, *args)
72
+ options = args.last.is_a?(Hash) ? args.pop : {}
73
+ args.each do |filter|
74
+ define_filter(type, filter, options)
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ module InstanceMethods
81
+
82
+ private
83
+
84
+ # Get back to class filters.
85
+ #
86
+ def filters
87
+ self.class.filters
88
+ end
89
+
90
+ # Predicate which uses the filter options to determine if the filter
91
+ # should be called. Specifically checks the :if, :unless, :only, and :except
92
+ # options for every filter. Each option check is expected to return false
93
+ # if the filter should not be invoked, true if invocation should occur.
94
+ #
95
+ def invoke_filter?(rpc_method, filter)
96
+ return invoke_via_only?(rpc_method, filter) \
97
+ && invoke_via_except?(rpc_method, filter) \
98
+ && invoke_via_if?(rpc_method, filter) \
99
+ && invoke_via_unless?(rpc_method, filter)
100
+ end
101
+
102
+ # If the target rpc endpoint method is listed under an :except option,
103
+ # return false to indicate that the filter should not be invoked. Any
104
+ # other target rpc endpoint methods not listed should be invoked.
105
+ # This option is the opposite of :only.
106
+ #
107
+ # Value should be a symbol/string or an array of symbols/strings.
108
+ #
109
+ def invoke_via_except?(rpc_method, filter)
110
+ except = [ filter.fetch(:except) { [] } ].flatten
111
+ return except.empty? || ! except.include?(rpc_method)
112
+ end
113
+
114
+ # Invoke the given :if callable (if any) and return its return value.
115
+ # Used by `invoke_filter?` which expects a true/false
116
+ # return value to determine if we should invoke the target filter.
117
+ #
118
+ # Value can either be a symbol/string indicating an instance method to call
119
+ # or an object that responds to `call`.
120
+ #
121
+ def invoke_via_if?(rpc_method, filter)
122
+ if_check = filter.fetch(:if) { lambda { |service| return true } }
123
+ do_invoke = case
124
+ when if_check.nil? then
125
+ true
126
+ else
127
+ call_or_send(if_check)
128
+ end
129
+
130
+ return do_invoke
131
+ end
132
+
133
+ # If the target rpc endpoint method is listed in the :only option,
134
+ # it should be invoked. Any target rpc endpoint methods not listed in this
135
+ # option should not be invoked. This option is the opposite of :except.
136
+ #
137
+ # Value should be a symbol/string or an array of symbols/strings.
138
+ #
139
+ def invoke_via_only?(rpc_method, filter)
140
+ only = [ filter.fetch(:only) { [] } ].flatten
141
+ return only.empty? || only.include?(rpc_method)
142
+ end
143
+
144
+ # Invoke the given :unless callable (if any) and return the opposite
145
+ # of it's return value. Used by `invoke_filter?` which expects a true/false
146
+ # return value to determine if we should invoke the target filter.
147
+ #
148
+ # Value can either be a symbol/string indicating an instance method to call
149
+ # or an object that responds to `call`.
150
+ #
151
+ def invoke_via_unless?(rpc_method, filter)
152
+ unless_check = filter.fetch(:unless) { lambda { |service| return false } }
153
+ skip_invoke = case
154
+ when unless_check.nil? then
155
+ false
156
+ else
157
+ call_or_send(unless_check)
158
+ end
159
+
160
+ return ! skip_invoke
161
+ end
162
+
163
+ def rescue_filters
164
+ self.class.rescue_filters
165
+ end
166
+
167
+ # Loop over the unwrapped filters and invoke them. An unwrapped filter
168
+ # is either a before or after filter, not an around filter.
169
+ #
170
+ def run_unwrapped_filters(unwrapped_filters, rpc_method, stop_on_false_return = false)
171
+ unwrapped_filters.each do |filter|
172
+ if invoke_filter?(rpc_method, filter)
173
+ return_value = call_or_send(filter[:callable])
174
+ return false if stop_on_false_return && return_value == false
175
+ end
176
+ end
177
+
178
+ return true
179
+ end
180
+
181
+ # Reverse build a chain of around filters. To implement an around chain,
182
+ # simply build a method that yields control when it expects the underlying
183
+ # method to be invoked. If the endpoint should not be run (due to some
184
+ # condition), simply do not yield.
185
+ #
186
+ # Around filters are invoked in the order they are defined, outer to inner,
187
+ # with the inner-most method called being the actual rpc endpoint.
188
+ #
189
+ # Let's say you have a class defined with the following filters:
190
+ #
191
+ # class MyService
192
+ # around_filter :filter1, :filter2, :filter3
193
+ #
194
+ # def my_endpoint
195
+ # # do stuff
196
+ # end
197
+ # end
198
+ #
199
+ # When the my_endpoint method is invoked using Service#callable_rpc_method,
200
+ # It is similar to this call chain:
201
+ #
202
+ # filter1 do
203
+ # filter2 do
204
+ # filter3 do
205
+ # my_endpoint
206
+ # end
207
+ # end
208
+ # end
209
+ #
210
+ def run_around_filters(rpc_method)
211
+ final = lambda { __send__(rpc_method) }
212
+ filters[:around].reverse.inject(final) { |previous, filter|
213
+ if invoke_filter?(rpc_method, filter)
214
+ lambda { call_or_send(filter[:callable], &previous) }
215
+ else
216
+ previous
217
+ end
218
+ }.call
219
+ end
220
+
221
+
222
+ # Entry method to call each filter type in the appropriate order. This should
223
+ # be used instead of the other run methods directly.
224
+ #
225
+ def run_filters(rpc_method)
226
+ run_rescue_filters do
227
+ continue = run_unwrapped_filters(filters[:before], rpc_method, true)
228
+ if continue
229
+ run_around_filters(rpc_method)
230
+ run_unwrapped_filters(filters[:after], rpc_method)
231
+ end
232
+ end
233
+ end
234
+
235
+ def run_rescue_filters
236
+ if rescue_filters.keys.empty?
237
+ yield
238
+ else
239
+ begin
240
+ yield
241
+ rescue *rescue_filters.keys => ex
242
+ call_or_send(rescue_filters[ex.class], ex)
243
+ end
244
+ end
245
+ end
246
+
247
+ # Call the object if it is callable, otherwise invoke the method using
248
+ # __send__ assuming that we respond_to it. Return the call's return value.
249
+ #
250
+ def call_or_send(callable, *args, &block)
251
+ return_value = case
252
+ when callable.respond_to?(:call) then
253
+ callable.call(self, *args, &block)
254
+ when respond_to?(callable, true) then
255
+ __send__(callable, *args, &block)
256
+ else
257
+ raise "Object #{callable} is not callable"
258
+ end
259
+
260
+ return return_value
261
+ end
262
+
263
+ end
264
+
265
+ end
266
+ end
267
+ end