protobuf 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile.lock +1 -1
- data/README.md +138 -126
- data/bin/rpc_server +2 -2
- data/bin/rprotoc +2 -2
- data/examples/reading_a_message.rb +3 -3
- data/examples/writing_a_message.rb +3 -3
- data/lib/protobuf.rb +3 -0
- data/lib/protobuf/compiler/nodes.rb +1 -1
- data/lib/protobuf/compiler/proto_parser.rb +16 -16
- data/lib/protobuf/compiler/visitors.rb +11 -25
- data/lib/protobuf/descriptor/descriptor_builder.rb +58 -58
- data/lib/protobuf/descriptor/field_descriptor.rb +2 -2
- data/lib/protobuf/ext/eventmachine.rb +16 -0
- data/lib/protobuf/message/decoder.rb +6 -6
- data/lib/protobuf/message/field.rb +14 -14
- data/lib/protobuf/message/message.rb +4 -4
- data/lib/protobuf/rpc/client.rb +42 -183
- data/lib/protobuf/rpc/connector.rb +19 -0
- data/lib/protobuf/rpc/connectors/base.rb +29 -0
- data/lib/protobuf/rpc/connectors/em_client.rb +227 -0
- data/lib/protobuf/rpc/connectors/eventmachine.rb +84 -0
- data/lib/protobuf/rpc/connectors/socket.rb +14 -0
- data/lib/protobuf/rpc/service.rb +4 -4
- data/lib/protobuf/version.rb +1 -1
- data/protobuf.gemspec +3 -3
- data/spec/helper/all.rb +13 -0
- data/spec/helper/server.rb +36 -0
- data/spec/helper/tolerance_matcher.rb +40 -0
- data/spec/spec_helper.rb +3 -5
- data/spec/unit/rpc/client_spec.rb +174 -0
- data/spec/unit/rpc/connector_spec.rb +36 -0
- data/spec/unit/rpc/connectors/base_spec.rb +77 -0
- data/spec/unit/rpc/connectors/eventmachine/client_spec.rb +0 -0
- data/spec/unit/rpc/connectors/eventmachine_spec.rb +0 -0
- data/spec/unit/{server_spec.rb → rpc/server_spec.rb} +0 -0
- data/spec/unit/{service_spec.rb → rpc/service_spec.rb} +0 -0
- metadata +79 -63
- data/lib/protobuf/compiler/template/rpc_bin.erb +0 -4
- data/lib/protobuf/compiler/template/rpc_client.erb +0 -18
- data/lib/protobuf/compiler/template/rpc_service.erb +0 -25
- data/lib/protobuf/rpc/client_connection.rb +0 -225
- 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
|
67
|
-
|
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)
|
data/lib/protobuf/rpc/client.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
|
-
require '
|
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 '
|
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
|
-
|
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
|
29
|
-
raise "Invalid client configuration. Service must be defined." if !
|
30
|
-
@
|
31
|
-
|
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,
|
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)
|
44
|
-
#
|
45
|
-
# end
|
39
|
+
# client = Client.new(:service => WidgetService)
|
40
|
+
# client.on_success {|res| ... }
|
46
41
|
#
|
47
|
-
def on_success &
|
48
|
-
@
|
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,
|
48
|
+
# is called, success_cb will NOT be called.
|
54
49
|
# Callback is called regardless of :async setting.
|
55
50
|
#
|
56
|
-
# Client(:service => WidgetService)
|
57
|
-
#
|
58
|
-
# end
|
51
|
+
# client = Client.new(:service => WidgetService)
|
52
|
+
# client.on_failure {|err| ... }
|
59
53
|
#
|
60
|
-
def on_failure &
|
61
|
-
@
|
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
|
-
#
|
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).
|
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
|
72
|
-
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
|
-
|
80
|
-
log_debug '[client] Request Type: %s' %
|
81
|
-
|
82
|
-
log_debug '[client] Response Type: %s' %
|
83
|
-
|
84
|
-
|
85
|
-
log_debug '[client] Request Data: %s' %
|
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
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
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
|
-
|
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
|