protobuf 1.0.0 → 1.0.1

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 (42) hide show
  1. data/Gemfile.lock +1 -1
  2. data/README.md +138 -126
  3. data/bin/rpc_server +2 -2
  4. data/bin/rprotoc +2 -2
  5. data/examples/reading_a_message.rb +3 -3
  6. data/examples/writing_a_message.rb +3 -3
  7. data/lib/protobuf.rb +3 -0
  8. data/lib/protobuf/compiler/nodes.rb +1 -1
  9. data/lib/protobuf/compiler/proto_parser.rb +16 -16
  10. data/lib/protobuf/compiler/visitors.rb +11 -25
  11. data/lib/protobuf/descriptor/descriptor_builder.rb +58 -58
  12. data/lib/protobuf/descriptor/field_descriptor.rb +2 -2
  13. data/lib/protobuf/ext/eventmachine.rb +16 -0
  14. data/lib/protobuf/message/decoder.rb +6 -6
  15. data/lib/protobuf/message/field.rb +14 -14
  16. data/lib/protobuf/message/message.rb +4 -4
  17. data/lib/protobuf/rpc/client.rb +42 -183
  18. data/lib/protobuf/rpc/connector.rb +19 -0
  19. data/lib/protobuf/rpc/connectors/base.rb +29 -0
  20. data/lib/protobuf/rpc/connectors/em_client.rb +227 -0
  21. data/lib/protobuf/rpc/connectors/eventmachine.rb +84 -0
  22. data/lib/protobuf/rpc/connectors/socket.rb +14 -0
  23. data/lib/protobuf/rpc/service.rb +4 -4
  24. data/lib/protobuf/version.rb +1 -1
  25. data/protobuf.gemspec +3 -3
  26. data/spec/helper/all.rb +13 -0
  27. data/spec/helper/server.rb +36 -0
  28. data/spec/helper/tolerance_matcher.rb +40 -0
  29. data/spec/spec_helper.rb +3 -5
  30. data/spec/unit/rpc/client_spec.rb +174 -0
  31. data/spec/unit/rpc/connector_spec.rb +36 -0
  32. data/spec/unit/rpc/connectors/base_spec.rb +77 -0
  33. data/spec/unit/rpc/connectors/eventmachine/client_spec.rb +0 -0
  34. data/spec/unit/rpc/connectors/eventmachine_spec.rb +0 -0
  35. data/spec/unit/{server_spec.rb → rpc/server_spec.rb} +0 -0
  36. data/spec/unit/{service_spec.rb → rpc/service_spec.rb} +0 -0
  37. metadata +79 -63
  38. data/lib/protobuf/compiler/template/rpc_bin.erb +0 -4
  39. data/lib/protobuf/compiler/template/rpc_client.erb +0 -18
  40. data/lib/protobuf/compiler/template/rpc_service.erb +0 -25
  41. data/lib/protobuf/rpc/client_connection.rb +0 -225
  42. data/spec/unit/client_spec.rb +0 -128
@@ -168,13 +168,6 @@ module Protobuf
168
168
  @file_contents
169
169
  end
170
170
 
171
- def create_bin(out_dir, underscored_name, module_name, service_name, default_port)
172
- bin_filename = "#{out_dir}/bin/start_#{underscored_name}"
173
- bin_contents = template_erb('rpc_bin').result(binding)
174
- create_file_with_backup(bin_filename, bin_contents, true) if @create_file
175
- @file_contents[bin_filename] = bin_contents
176
- end
177
-
178
171
  def create_service(message_file, out_dir, underscored_name, module_name, service_name, default_port, rpcs, required_file)
179
172
  service_filename = "#{out_dir}/#{Util.module_to_path(module_name)}/#{underscored_name}.rb"
180
173
  service_contents = template_erb('rpc_service_implementation').result(binding)
@@ -182,13 +175,6 @@ module Protobuf
182
175
  @file_contents[service_filename] = service_contents
183
176
  end
184
177
 
185
- def create_client(out_dir, underscored_name, default_port, name, request, response, message_module, required_file)
186
- client_filename = "#{out_dir}/clients/#{Util.module_to_path(message_module)}_client_#{underscore name}.rb"
187
- client_contents = template_erb('rpc_client').result binding
188
- create_file_with_backup(client_filename, client_contents, true) if @create_file
189
- @file_contents[client_filename] = client_contents
190
- end
191
-
192
178
  private
193
179
 
194
180
  def underscore(str)
@@ -232,19 +218,19 @@ module Protobuf
232
218
  def add_option(name, value)
233
219
  options =
234
220
  case current_descriptor
235
- when Google::Protobuf::FileDescriptorProto
221
+ when Google::Protobuf::FileDescriptorProto then
236
222
  Google::Protobuf::FileOptions.new
237
- when Google::Protobuf::DescriptorProto
223
+ when Google::Protobuf::DescriptorProto then
238
224
  Google::Protobuf::MessageOptions.new
239
- when Google::Protobuf::FieldDescriptorProto
225
+ when Google::Protobuf::FieldDescriptorProto then
240
226
  Google::Protobuf::FieldOptions.new
241
- when Google::Protobuf::EnumDescriptorProto
227
+ when Google::Protobuf::EnumDescriptorProto then
242
228
  Google::Protobuf::EnumOptions.new
243
- when Google::Protobuf::EnumValueDescriptorProto
229
+ when Google::Protobuf::EnumValueDescriptorProto then
244
230
  Google::Protobuf::EnumValueOptions.new
245
- when Google::Protobuf::ServiceDescriptorProto
231
+ when Google::Protobuf::ServiceDescriptorProto then
246
232
  Google::Protobuf::ServiceOptions.new
247
- when Google::Protobuf::MethodDescriptorProto
233
+ when Google::Protobuf::MethodDescriptorProto then
248
234
  Google::Protobuf::MethodOptions.new
249
235
  else
250
236
  raise ArgumentError, 'Invalid context'
@@ -255,9 +241,9 @@ module Protobuf
255
241
 
256
242
  def descriptor=(descriptor)
257
243
  case current_descriptor
258
- when Google::Protobuf::FileDescriptorProto
244
+ when Google::Protobuf::FileDescriptorProto then
259
245
  current_descriptor.message_type << descriptor
260
- when Google::Protobuf::DescriptorProto
246
+ when Google::Protobuf::DescriptorProto then
261
247
  current_descriptor.nested_type << descriptor
262
248
  else
263
249
  raise ArgumentError, 'Invalid context'
@@ -283,9 +269,9 @@ module Protobuf
283
269
 
284
270
  def field_descriptor=(descriptor)
285
271
  case current_descriptor
286
- when Google::Protobuf::FileDescriptorProto
272
+ when Google::Protobuf::FileDescriptorProto then
287
273
  current_descriptor.extension << descriptor
288
- when Google::Protobuf::DescriptorProto
274
+ when Google::Protobuf::DescriptorProto then
289
275
  current_descriptor.field << descriptor
290
276
  #TODO: how should i distiguish between field and extension
291
277
  #current_descriptor.extension << descriptor
@@ -5,41 +5,41 @@ module Protobuf
5
5
  def self.id2type(type_id)
6
6
  require 'protobuf/descriptor/descriptor_proto'
7
7
  case type_id
8
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_DOUBLE
8
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_DOUBLE then
9
9
  :double
10
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_FLOAT
10
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_FLOAT then
11
11
  :float
12
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT64
12
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT64 then
13
13
  :int64
14
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT64
14
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT64 then
15
15
  :unit64
16
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT32
16
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT32 then
17
17
  :int64
18
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED64
18
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED64 then
19
19
  :fixed64
20
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED32
20
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED32 then
21
21
  :fixed32
22
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_BOOL
22
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_BOOL then
23
23
  :bool
24
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
24
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING then
25
25
  :string
26
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_GROUP
26
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_GROUP then
27
27
  :group
28
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
28
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE then
29
29
  :message
30
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_BYTES
30
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_BYTES then
31
31
  :bytes
32
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT32
32
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT32 then
33
33
  :uint32
34
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_ENUM
34
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_ENUM then
35
35
  :enum
36
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED32
36
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED32 then
37
37
  :sfixed32
38
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED64
38
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED64 then
39
39
  :sfixed64
40
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT32
40
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT32 then
41
41
  :sint32
42
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT64
42
+ when Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT64 then
43
43
  :sint64
44
44
  else
45
45
  raise ArgumentError, "Invalid type: #{proto.type}"
@@ -49,42 +49,42 @@ module Protobuf
49
49
  def self.type2id(type)
50
50
  require 'protobuf/descriptor/descriptor_proto'
51
51
  case type
52
- when :double
53
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_DOUBLE
54
- when :float
52
+ when :double then
53
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_DOUBLE
54
+ when :float then
55
55
  Google::Protobuf::FieldDescriptorProto::Type::TYPE_FLOAT
56
- when :int64
57
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT64
58
- when :unit64
59
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT64
60
- when :int64
61
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT32
62
- when :fixed64
63
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED64
64
- when :fixed32
65
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED32
66
- when Google::Protobuf::FieldDescriptorProto::Type::TYPE_BOOL
67
- :bool
68
- when :string
69
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
70
- when :group
71
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_GROUP
72
- when :message
73
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
74
- when :bytes
56
+ when :int64 then
57
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT64
58
+ when :unit64 then
59
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT64
60
+ when :int64 then
61
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_INT32
62
+ when :fixed64 then
63
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED64
64
+ when :fixed32 then
65
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_FIXED32
66
+ when :bool then
67
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_BOOL
68
+ when :string then
69
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_STRING
70
+ when :group then
71
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_GROUP
72
+ when :message then
73
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
74
+ when :bytes then
75
75
  Google::Protobuf::FieldDescriptorProto::Type::TYPE_BYTES
76
- when :uint32
77
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT32
78
- when :enum
79
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_ENUM
80
- when :sfixed32
81
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED32
82
- when :sfixed64
83
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED64
84
- when :sint32
85
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT32
86
- when :sint64
87
- Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT64
76
+ when :uint32 then
77
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_UINT32
78
+ when :enum then
79
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_ENUM
80
+ when :sfixed32 then
81
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED32
82
+ when :sfixed64 then
83
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_SFIXED64
84
+ when :sint32 then
85
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT32
86
+ when :sint64 then
87
+ Google::Protobuf::FieldDescriptorProto::Type::TYPE_SINT64
88
88
  else
89
89
  Google::Protobuf::FieldDescriptorProto::Type::TYPE_MESSAGE
90
90
  end
@@ -93,11 +93,11 @@ module Protobuf
93
93
  def self.id2label(label_id)
94
94
  require 'protobuf/descriptor/descriptor_proto'
95
95
  case label_id
96
- when Google::Protobuf::FieldDescriptorProto::Label::LABEL_REQUIRED
96
+ when Google::Protobuf::FieldDescriptorProto::Label::LABEL_REQUIRED then
97
97
  :required
98
- when Google::Protobuf::FieldDescriptorProto::Label::LABEL_OPTIONAL
98
+ when Google::Protobuf::FieldDescriptorProto::Label::LABEL_OPTIONAL then
99
99
  :optional
100
- when Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED
100
+ when Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED then
101
101
  :repeated
102
102
  else
103
103
  raise ArgumentError, "Invalid label: #{proto.label}"
@@ -108,11 +108,11 @@ module Protobuf
108
108
  require 'protobuf/descriptor/descriptor_proto'
109
109
  case label
110
110
  when :required
111
- Google::Protobuf::FieldDescriptorProto::Label::LABEL_REQUIRED
111
+ Google::Protobuf::FieldDescriptorProto::Label::LABEL_REQUIRED then
112
112
  when :optional
113
- Google::Protobuf::FieldDescriptorProto::Label::LABEL_OPTIONAL
113
+ Google::Protobuf::FieldDescriptorProto::Label::LABEL_OPTIONAL then
114
114
  when :repeated
115
- Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED
115
+ Google::Protobuf::FieldDescriptorProto::Label::LABEL_REPEATED then
116
116
  else
117
117
  raise ArgumentError, "Invalid label: #{label}"
118
118
  end
@@ -32,9 +32,9 @@ module Protobuf
32
32
  field_proto.default_value = @field_instance.default.to_s if @field_instance.default
33
33
 
34
34
  case parent_proto
35
- when Google::Protobuf::FileDescriptorProto
35
+ when Google::Protobuf::FileDescriptorProto then
36
36
  parent_proto.extension << field_proto
37
- when Google::Protobuf::DescriptorProto
37
+ when Google::Protobuf::DescriptorProto then
38
38
  if extension
39
39
  parent_proto.extension << field_proto
40
40
  else
@@ -0,0 +1,16 @@
1
+ require 'fiber'
2
+
3
+ # Method and concept from em-synchrony
4
+ # https://github.com/igrigorik/em-synchrony
5
+ #
6
+ # A convenience method for wrapping EM.run body within
7
+ # a Ruby Fiber such that async operations can be transparently
8
+ # paused and resumed based on IO scheduling
9
+ module EventMachine
10
+ def self.fiber_run(blk=nil, tail=nil, &block)
11
+ blk ||= block
12
+ context = Proc.new{ Fiber.new{ blk.call }.resume }
13
+
14
+ self.run(context, tail)
15
+ end
16
+ end
@@ -13,17 +13,17 @@ module Protobuf
13
13
  tag, wire_type = read_key(stream)
14
14
  bytes =
15
15
  case wire_type
16
- when WireType::VARINT
16
+ when WireType::VARINT then
17
17
  read_varint(stream)
18
- when WireType::FIXED64
18
+ when WireType::FIXED64 then
19
19
  read_fixed64(stream)
20
- when WireType::LENGTH_DELIMITED
20
+ when WireType::LENGTH_DELIMITED then
21
21
  read_length_delimited(stream)
22
- when WireType::START_GROUP
22
+ when WireType::START_GROUP then
23
23
  read_start_group(stream)
24
- when WireType::END_GROUP
24
+ when WireType::END_GROUP then
25
25
  read_end_group(stream)
26
- when WireType::FIXED32
26
+ when WireType::FIXED32 then
27
27
  read_fixed32(stream)
28
28
  else
29
29
  raise InvalidWireType, wire_type
@@ -59,11 +59,11 @@ module Protobuf
59
59
 
60
60
  @default_value = \
61
61
  case @rule
62
- when :repeated
62
+ when :repeated then
63
63
  FieldArray.new(self).freeze
64
- when :required
64
+ when :required then
65
65
  nil
66
- when :optional
66
+ when :optional then
67
67
  typed_default_value
68
68
  end
69
69
 
@@ -77,11 +77,11 @@ module Protobuf
77
77
  def initialized?(message_instance)
78
78
  value = message_instance.__send__(@name)
79
79
  case @rule
80
- when :required
80
+ when :required then
81
81
  ! value.nil? && (! kind_of?(MessageField) || value.initialized?)
82
- when :repeated
82
+ when :repeated then
83
83
  value.all? {|msg| ! kind_of?(MessageField) || msg.initialized? }
84
- when :optional
84
+ when :optional then
85
85
  value.nil? || ! kind_of?(MessageField) || value.initialized?
86
86
  end
87
87
  end
@@ -625,11 +625,11 @@ module Protobuf
625
625
  @message_class.class_eval do
626
626
  define_method("#{field.name}=") do |val|
627
627
  case val
628
- when nil
628
+ when nil then
629
629
  @values.delete(field.name)
630
- when Hash
630
+ when Hash then
631
631
  @values[field.name] = field.type.new(val)
632
- when field.type
632
+ when field.type then
633
633
  @values[field.name] = val
634
634
  else
635
635
  raise TypeError, "Expected value of type '#{field.type}', but got '#{val.class}'"
@@ -647,9 +647,9 @@ module Protobuf
647
647
  class EnumField < VarintField
648
648
  def acceptable?(val)
649
649
  case val
650
- when Symbol
650
+ when Symbol then
651
651
  raise TypeError unless @type.const_defined?(val)
652
- when EnumValue
652
+ when EnumValue then
653
653
  raise TypeError if val.parent_class != @type
654
654
  else
655
655
  raise TypeError unless @type.valid_tag?(val)
@@ -680,11 +680,11 @@ module Protobuf
680
680
  else
681
681
  val = \
682
682
  case val
683
- when Symbol
683
+ when Symbol then
684
684
  field.type.const_get(val) rescue nil
685
- when Integer
685
+ when Integer then
686
686
  field.type.const_get(field.type.name_by_value(val)) rescue nil
687
- when EnumValue
687
+ when EnumValue then
688
688
  raise TypeError, "Invalid value: #{val.inspect}" if val.parent_class != field.type
689
689
  val
690
690
  end
@@ -213,13 +213,13 @@ module Protobuf
213
213
  ''
214
214
  else
215
215
  case field
216
- when Field::MessageField
216
+ when Field::MessageField then
217
217
  if value.nil?
218
218
  "#{i}#{field.name} {}\n"
219
219
  else
220
220
  "#{i}#{field.name} {\n#{value.inspect(indent + 1)}#{i}}\n"
221
221
  end
222
- when Field::EnumField
222
+ when Field::EnumField then
223
223
  if value.is_a?(EnumValue)
224
224
  "#{i}#{field.name}: #{value.name}\n"
225
225
  else
@@ -368,9 +368,9 @@ module Protobuf
368
368
  build_value = lambda {|field, value|
369
369
  if !field.optional? || (field.optional? && has_field?(field.name))
370
370
  case field
371
- when Field::MessageField
371
+ when Field::MessageField then
372
372
  value.to_hash
373
- when Field::EnumField
373
+ when Field::EnumField then
374
374
  if value.is_a?(EnumValue)
375
375
  value.to_i
376
376
  elsif value.is_a?(Symbol)
@@ -1,16 +1,16 @@
1
- require 'eventmachine'
1
+ require 'forwardable'
2
2
  require 'protobuf/common/logger'
3
- require 'protobuf/rpc/client_connection'
4
- require 'protobuf/rpc/buffer'
5
3
  require 'protobuf/rpc/error'
6
- require 'timeout'
4
+ require 'protobuf/rpc/connector'
7
5
 
8
6
  module Protobuf
9
7
  module Rpc
10
8
  class Client
9
+ extend Forwardable
11
10
  include Protobuf::Logger::LogMethods
12
11
 
13
- attr_reader :error, :options, :do_block
12
+ delegate [:options, :success_cb, :failure_cb, :async?] => :@connector
13
+ attr_reader :connector
14
14
 
15
15
  # Create a new client with default options (defined in ClientConnection)
16
16
  # See Service#client for a more convenient way to create a client, as well
@@ -25,83 +25,68 @@ module Protobuf
25
25
  # :request => request
26
26
  # })
27
27
  #
28
- def initialize options={}
29
- raise "Invalid client configuration. Service must be defined." if !options[:service] || options[:service].nil?
30
- @error = {}
31
- @options = ClientConnection::DEFAULT_OPTIONS.merge(options)
32
- @success_callback = nil
33
- @failure_callback = nil
34
- @do_block = !@options[:async]
35
- log_debug '[client] Initialized with options: %s' % @options.inspect
28
+ def initialize opts={}
29
+ raise "Invalid client configuration. Service must be defined." if !opts[:service] || opts[:service].nil?
30
+ @connector = Connector.connector_for_platform.new(opts)
31
+ log_debug '[client] Initialized with options: %s' % opts.inspect
36
32
  end
37
33
 
38
34
  # Set a success callback on the client to return the
39
35
  # successful response from the service when it is returned.
40
- # If this callback is called, failure_callback will NOT be called.
36
+ # If this callback is called, failure_cb will NOT be called.
41
37
  # Callback is called regardless of :async setting.
42
38
  #
43
- # Client(:service => WidgetService).new.find do |c|
44
- # c.on_success {|res| ... }
45
- # end
39
+ # client = Client.new(:service => WidgetService)
40
+ # client.on_success {|res| ... }
46
41
  #
47
- def on_success &success_callback
48
- @success_callback = success_callback
42
+ def on_success &success_cb
43
+ @connector.success_cb = success_cb
49
44
  end
50
45
 
51
46
  # Set a failure callback on the client to return the
52
47
  # error returned by the service, if any. If this callback
53
- # is called, success_callback will NOT be called.
48
+ # is called, success_cb will NOT be called.
54
49
  # Callback is called regardless of :async setting.
55
50
  #
56
- # Client(:service => WidgetService).new.find do |c|
57
- # c.on_failure {|err| ... }
58
- # end
51
+ # client = Client.new(:service => WidgetService)
52
+ # client.on_failure {|err| ... }
59
53
  #
60
- def on_failure &failure_callback
61
- @failure_callback = failure_callback
54
+ def on_failure &failure_cb
55
+ @connector.failure_cb = failure_cb
62
56
  end
63
57
 
64
58
  # Provides a mechanism to call the service method against the client
65
- # and will automatically setup the service_class and method_name
59
+ # which will automatically setup the service_class and method_name
66
60
  # in the wrapper protobuf request.
67
61
  #
68
- # # find is not defined by Client which will trigger method_missing
69
- # Client(:service => WidgetService).new.find
62
+ # # The :find method is not defined by Client which will trigger method_missing
63
+ # Client.new(:service => WidgetService).find do |c|
64
+ # # This block will be invoked before the request is made
65
+ # # `c` in this case is the client object you created above
66
+ # c.on_success {|res| ... }
67
+ # c.on_failure {|err| ... }
68
+ # end
70
69
  #
71
- def method_missing method, *params, &client_callback
72
- service = @options[:service]
70
+ def method_missing method, *params
71
+ service = options[:service]
73
72
  unless service.rpcs[service].keys.include?(method)
74
73
  log_error '[client] %s#%s not rpc method, passing to super' % [service.name, method.to_s]
75
74
  super method, *params
76
75
  else
77
76
  log_debug '[client] %s#%s' % [service.name, method.to_s]
78
77
  rpc = service.rpcs[service][method.to_sym]
79
- @options[:request_type] = rpc.request_type
80
- log_debug '[client] Request Type: %s' % @options[:request_type].name
81
- @options[:response_type] = rpc.response_type
82
- log_debug '[client] Response Type: %s' % @options[:response_type].name
83
- @options[:method] = method.to_s
84
- @options[:request] = params[0].is_a?(Hash) ? @options[:request_type].new(params[0]) : params[0]
85
- log_debug '[client] Request Data: %s' % @options[:request].inspect
78
+ options[:request_type] = rpc.request_type
79
+ log_debug '[client] Request Type: %s' % options[:request_type].name
80
+ options[:response_type] = rpc.response_type
81
+ log_debug '[client] Response Type: %s' % options[:response_type].name
82
+ options[:method] = method.to_s
83
+ options[:request] = params[0].is_a?(Hash) ? options[:request_type].new(params[0]) : params[0]
84
+ log_debug '[client] Request Data: %s' % options[:request].inspect
86
85
 
87
- #### TODO remove first part here once we are able to convert everything to the new event based way of handling success/failure
88
- unless client_callback.nil?
89
- if client_callback.arity == 2
90
- @options[:version] = 1.0
91
- log_debug '[client] version = 1.0'
92
-
93
- log_warn deprecation_warning
94
- STDOUT.puts deprecation_warning unless Protobuf::Logger.configured?
95
-
96
- on_success {|res| client_callback.call(self, res) }
97
- on_failure {|err| client_callback.call(self, nil) }
98
- else
99
- ### TODO Replace block above with this once all client definitions use new event driven approach
100
- # Call client to setup on_success and on_failure event callbacks
101
- @options[:version] = 2.0
102
- log_debug '[client] version = 2.0'
103
- client_callback.call(self)
104
- end
86
+ # Call client to setup on_success and on_failure event callbacks
87
+ if block_given?
88
+ log_debug '[client] client setup callback given, invoking'
89
+ yield(self)
105
90
  else
106
91
  log_debug '[client] no callbacks given'
107
92
  end
@@ -134,135 +119,9 @@ module Protobuf
134
119
  # client.send_request
135
120
  #
136
121
  def send_request
137
- Thread.new { EM.run } unless EM.reactor_running?
138
-
139
- EM.schedule do
140
- log_debug '[client] Scheduling client connection to be created on next tick'
141
- connection = ClientConnection.connect @options, &ensure_callback
142
- connection.on_success &@success_callback unless @success_callback.nil?
143
- connection.on_failure &ensure_callback
144
- connection.on_complete { @do_block = false } if @do_block
145
- log_debug '[client] Connection scheduled'
146
- end
147
-
148
- return synchronize_or_return
149
- end
150
-
151
- # Block the client call to send_request from returning if
152
- # async is false, otherwise do nothing.
153
- # Simple blocking algorithm to sleep while @do_block is set to true.
154
- # The eventmachine connection has a registered callback to flip
155
- # @do_block to false as soon as the response has been received and processed.
156
- # If any errors are returned an appropriate RPC_ERROR is sent back to the client
157
- # through the failure callback.
158
- #
159
- def synchronize_or_return
160
- if @do_block
161
- begin
162
- Timeout.timeout(@options[:timeout]) do
163
- sleep 0.5 while @do_block
164
- true
165
- end
166
- rescue => ex
167
- log_error 'An exception occurred while waiting for server response:'
168
- log_error ex.message
169
- log_error ex.backtrace.join("\n")
170
-
171
- if ex.is_a?(Timeout::Error)
172
- message = 'Client timeout of %d seconds expired' % @options[:timeout]
173
- else
174
- message = 'Client failed: %s' % ex.message
175
- end
176
-
177
- err = ClientError.new(Protobuf::Socketrpc::ErrorReason::RPC_ERROR, message)
178
- ensure_callback.call(err)
179
- end
180
- else
181
- true
182
- end
183
- end
184
-
185
- # Returns a proc that ensures any errors will be returned to the client
186
- #
187
- # If a failure callback was set, just use that as a direct assignment
188
- # otherwise implement one here that simply throws an exception, since we
189
- # don't want to swallow the black holes.
190
- #
191
- # TODO: remove "else" portion below once 1.0 is gone
192
- #
193
- def ensure_callback
194
- @ensure_callback ||= begin
195
- if @options[:version] == 2.0
196
- if @failure_callback.nil?
197
- cbk = proc do |error|
198
- raise '%s: %s' % [error.code.name, error.message]
199
- end
200
- else
201
- cbk = @failure_callback
202
- end
203
- else
204
- cbk = proc do |error|
205
- @error = error
206
- @failure_callback ? @failure_callback.call(self) : raise('%s: %s' % [error.code.name, error.message])
207
- end
208
- end
209
- cbk
210
- end
211
- end
212
-
213
- # Annoying deprecation warning to print if you are still on v1 DSL
214
- def deprecation_warning
215
- %Q{
216
- ##################################################
217
- # Deprecation Warning - Upgrade Client Callbacks
218
- # ==============================================
219
- #
220
- # You are attempting to use two block arguments (presumably client and response)
221
- # in your client callback for the call to #{@options[:service].name}.client.#{@options[:method]}.
222
- #
223
- # The next version of ruby-protobuf will completely remove the
224
- # style of client calls that accepts two arguments in favor of a more explicit evented approach.
225
- #
226
- # You should refactor the code before upgrading to the next version of this gem. An example of callback style v1:
227
- #
228
- # #{@options[:service]}.client.#{@options[:method]}(request) do |client, response|
229
- # if client.failed?
230
- # # do something with client.error or client.message
231
- # else
232
- # # do something with response
233
- # end
234
- # end
235
- #
236
- # Refactor the previous example of callback style v1 usage to v2 with the following:
237
- #
238
- # #{@options[:service]}.client.#{@options[:method]}(request) do |c|
239
- # c.on_failure do |error|
240
- # # do something with error.code or error.message
241
- # end
242
- # c.on_success do |response|
243
- # # do something with response
244
- # end
245
- # end
246
- #
247
- ##################################################
248
- }
249
- end
250
-
251
- # Controller error/failure methods
252
- # TODO remove these when v1 is gone
253
- def failed?
254
- !@error.nil? and !@error[:code].nil?
255
- end
256
- def error
257
- @error[:message] if failed?
258
- end
259
- def error_reason
260
- Protobuf::Socketrpc::ErrorReason.name_by_value(@error[:code]).to_s if failed?
261
- end
262
- def error_message
263
- "%s: %s" % [error_reason, error] if failed?
122
+ @connector.send_request
264
123
  end
265
124
 
266
125
  end
267
126
  end
268
- end
127
+ end