google-gax 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,338 @@
1
+ # Copyright 2016, Google Inc.
2
+ # All rights reserved.
3
+ #
4
+ # Redistribution and use in source and binary forms, with or without
5
+ # modification, are permitted provided that the following conditions are
6
+ # met:
7
+ #
8
+ # * Redistributions of source code must retain the above copyright
9
+ # notice, this list of conditions and the following disclaimer.
10
+ # * Redistributions in binary form must reproduce the above
11
+ # copyright notice, this list of conditions and the following disclaimer
12
+ # in the documentation and/or other materials provided with the
13
+ # distribution.
14
+ # * Neither the name of Google Inc. nor the names of its
15
+ # contributors may be used to endorse or promote products derived from
16
+ # this software without specific prior written permission.
17
+ #
18
+ # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19
+ # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20
+ # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21
+ # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22
+ # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23
+ # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24
+ # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25
+ # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26
+ # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27
+ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
+
30
+ require 'time'
31
+
32
+ require 'google/gax/operation'
33
+ require 'google/gax/settings'
34
+ require 'google/gax/constants'
35
+ require 'google/protobuf/any_pb'
36
+ require 'google/rpc/status_pb'
37
+ require 'google/longrunning/operations_pb'
38
+
39
+ GrpcOp = Google::Longrunning::Operation
40
+ GaxOp = Google::Gax::Operation
41
+
42
+ MILLIS_PER_SECOND = Google::Gax::MILLIS_PER_SECOND
43
+
44
+ class MockLroClient
45
+ def initialize(get_method: nil, cancel_method: nil)
46
+ @get_method = get_method
47
+ @cancel_method = cancel_method
48
+ end
49
+
50
+ def get_operation(grpc_method, options: nil)
51
+ @get_method.call(grpc_method, options)
52
+ end
53
+
54
+ def cancel_operation(name)
55
+ @cancel_method.call(name)
56
+ end
57
+ end
58
+
59
+ # TODO: This is from google/protobuf/well_known_types.rb.
60
+ # Using google/protobuf in gax-ruby is currently causing a dependency
61
+ # conflict with grpc. When grpc depends on google-protobuf v3.1.0
62
+ # remove this function and use Google::Protobuf::Any#pack.
63
+ def pack(any_pb, msg, type_url_prefix = 'type.googleapis.com/')
64
+ if type_url_prefix.empty? || type_url_prefix[-1] != '/'
65
+ any_pb.type_url = "#{type_url_prefix}/#{msg.class.descriptor.name}"
66
+ else
67
+ any_pb.type_url = "#{type_url_prefix}#{msg.class.descriptor.name}"
68
+ end
69
+ any_pb.value = msg.to_proto
70
+ end
71
+
72
+ RESULT_ANY = Google::Protobuf::Any.new
73
+ RESULT = Google::Rpc::Status.new(code: 1, message: 'Result')
74
+ pack(RESULT_ANY, RESULT)
75
+
76
+ METADATA_ANY = Google::Protobuf::Any.new
77
+ METADATA = Google::Rpc::Status.new(code: 2, message: 'Metadata')
78
+ pack(METADATA_ANY, METADATA)
79
+
80
+ DONE_GET_METHOD = proc do
81
+ GrpcOp.new(done: true, response: RESULT_ANY, metadata: METADATA_ANY)
82
+ end
83
+ DONE_ON_GET_CLIENT = MockLroClient.new(get_method: DONE_GET_METHOD)
84
+
85
+ def create_op(operation, client: nil, call_options: nil)
86
+ GaxOp.new(
87
+ operation,
88
+ client || DONE_ON_GET_CLIENT,
89
+ Google::Rpc::Status,
90
+ Google::Rpc::Status,
91
+ call_options: call_options
92
+ )
93
+ end
94
+
95
+ describe Google::Gax::Operation do
96
+ context 'method `results`' do
97
+ it 'should return nil on unfinished operation.' do
98
+ op = create_op(GrpcOp.new(done: false))
99
+ expect(op.results).to be_nil
100
+ end
101
+
102
+ it 'should return the error on errored operation.' do
103
+ error = Google::Rpc::Status.new
104
+ op = create_op(GrpcOp.new(done: true, error: error))
105
+ expect(op.results).to eq(error)
106
+ end
107
+
108
+ it 'should unpack the response' do
109
+ op = create_op(GrpcOp.new(done: true, response: RESULT_ANY))
110
+ expect(op.results).to eq(RESULT)
111
+ end
112
+ end
113
+
114
+ context 'method `metadata`' do
115
+ it 'should unpack the metadata' do
116
+ op = create_op(GrpcOp.new(done: true, metadata: METADATA_ANY))
117
+ expect(op.metadata).to eq(METADATA)
118
+ end
119
+ end
120
+
121
+ context 'method `done?`' do
122
+ it 'should return the status of an operation correctly.' do
123
+ expect(create_op(GrpcOp.new(done: false)).done?).to eq(false)
124
+ expect(create_op(GrpcOp.new(done: true)).done?).to eq(true)
125
+ end
126
+ end
127
+
128
+ context 'method `error?`' do
129
+ it 'should return false on unfinished operation.' do
130
+ expect(create_op(GrpcOp.new(done: false)).error?).to eq(false)
131
+ end
132
+
133
+ it 'should return true on error.' do
134
+ error = Google::Rpc::Status.new
135
+ op = create_op(GrpcOp.new(done: true, error: error))
136
+ expect(op.error?).to eq(true)
137
+ end
138
+
139
+ it 'should return true on finished operation.' do
140
+ op = create_op(GrpcOp.new(done: true, response: RESULT_ANY))
141
+ expect(op.error?).to eq(false)
142
+ end
143
+ end
144
+
145
+ context 'method `cancel`' do
146
+ it 'should call the clients cancel_operation' do
147
+ op_name = 'test_name'
148
+ called = false
149
+ cancel_method = proc do |name|
150
+ expect(name).to eq(op_name)
151
+ called = true
152
+ end
153
+ mock_client = MockLroClient.new(cancel_method: cancel_method)
154
+ create_op(GrpcOp.new(name: op_name), client: mock_client).cancel
155
+ expect(called).to eq(true)
156
+ end
157
+ end
158
+
159
+ context 'method `reload!`' do
160
+ it 'should call the get_operation of the client' do
161
+ called = false
162
+ get_method = proc do
163
+ called = true
164
+ GrpcOp.new(done: true, response: RESULT_ANY)
165
+ end
166
+ mock_client = MockLroClient.new(get_method: get_method)
167
+ op = create_op(GrpcOp.new(done: false), client: mock_client)
168
+ expect(called).to eq(false)
169
+ op.reload!
170
+ expect(called).to eq(true)
171
+ end
172
+
173
+ it 'should use call_options attribute when reloading' do
174
+ backoff_settings = Google::Gax::BackoffSettings.new(1, 2, 3, 4, 5, 6, 7)
175
+ call_options = Google::Gax::CallOptions.new(
176
+ retry_options: Google::Gax::RetryOptions.new(nil, backoff_settings)
177
+ )
178
+ called = false
179
+ get_method = proc do |_, options|
180
+ called = true
181
+ expect(options).to be_a(Google::Gax::CallOptions)
182
+ expect(options).to eq(call_options)
183
+ GrpcOp.new(done: true, response: RESULT_ANY)
184
+ end
185
+ mock_client = MockLroClient.new(get_method: get_method)
186
+
187
+ op = create_op(
188
+ GrpcOp.new(done: false, name: 'name'),
189
+ client: mock_client,
190
+ call_options: call_options
191
+ )
192
+ expect(called).to eq(false)
193
+ op.reload!
194
+ expect(called).to eq(true)
195
+ end
196
+
197
+ it 'should yield the registered callback after the operation completes' do
198
+ op = create_op(GrpcOp.new(done: false), client: DONE_ON_GET_CLIENT)
199
+ called = false
200
+ op.on_done do |operation|
201
+ expect(operation.results).to eq(RESULT)
202
+ expect(operation.metadata).to eq(METADATA)
203
+ called = true
204
+ end
205
+ expect(called).to eq(false)
206
+ expect(op.done?).to eq(false)
207
+ op.reload!
208
+ expect(called).to eq(true)
209
+ expect(op.done?).to eq(true)
210
+ end
211
+
212
+ it 'should yield the registered callbacks in order they were called.' do
213
+ op = create_op(GrpcOp.new(done: false), client: DONE_ON_GET_CLIENT)
214
+ expected_order = [1, 2, 3]
215
+ called_order = []
216
+ expected_order.each do |i|
217
+ op.on_done do |operation|
218
+ expect(operation.results).to eq(RESULT)
219
+ expect(operation.metadata).to eq(METADATA)
220
+ called_order.push(i)
221
+ end
222
+ end
223
+ expect(called_order).to eq([])
224
+ expect(op.done?).to eq(false)
225
+ op.reload!
226
+ expect(called_order).to eq(expected_order)
227
+ expect(op.done?).to eq(true)
228
+ end
229
+ end
230
+
231
+ context 'method `wait_until_done!`' do
232
+ it 'should retry until the operation is done' do
233
+ to_call = 3
234
+ get_method = proc do
235
+ to_call -= 1
236
+ done = to_call == 0
237
+ GrpcOp.new(done: done, response: RESULT_ANY)
238
+ end
239
+ mock_client = MockLroClient.new(get_method: get_method)
240
+ op = create_op(GrpcOp.new(done: false), client: mock_client)
241
+ time_now = Time.now
242
+ allow(Time).to receive(:now) { time_now }
243
+ expect(op).to receive(:sleep).exactly(3).times { |secs| time_now += secs }
244
+ op.wait_until_done!
245
+ expect(to_call).to eq(0)
246
+ end
247
+
248
+ it 'should wait until the operation is done' do
249
+ to_call = 3
250
+ get_method = proc do
251
+ to_call -= 1
252
+ done = to_call == 0
253
+ GrpcOp.new(done: done, response: RESULT_ANY)
254
+ end
255
+ mock_client = MockLroClient.new(get_method: get_method)
256
+ op = create_op(GrpcOp.new(done: false), client: mock_client)
257
+
258
+ time_now = Time.now
259
+ allow(Time).to receive(:now) { time_now }
260
+ expect(op).to receive(:sleep).exactly(3).times { |secs| time_now += secs }
261
+
262
+ op.wait_until_done!
263
+ expect(to_call).to eq(0)
264
+ end
265
+
266
+ it 'times out' do
267
+ backoff_settings = BackoffSettings.new(1, 1, 10, 0, 0, 0, 100)
268
+ get_method = proc { GrpcOp.new(done: false) }
269
+ mock_client = MockLroClient.new(get_method: get_method)
270
+ op = create_op(GrpcOp.new(done: false), client: mock_client)
271
+
272
+ time_now = Time.now
273
+ allow(Time).to receive(:now) { time_now }
274
+ allow(op).to receive(:sleep) { |secs| time_now += secs }
275
+
276
+ begin
277
+ op.wait_until_done!(backoff_settings: backoff_settings)
278
+ rescue Google::Gax::RetryError => exc
279
+ expect(exc).to be_a(Google::Gax::RetryError)
280
+ end
281
+ end
282
+
283
+ it 'retries with exponential backoff' do
284
+ call_count = 0
285
+ get_method = proc do
286
+ call_count += 1
287
+ GrpcOp.new(done: false, response: RESULT_ANY)
288
+ end
289
+ mock_client = MockLroClient.new(get_method: get_method)
290
+ op = create_op(GrpcOp.new(done: false), client: mock_client)
291
+
292
+ time_now = Time.now
293
+ start_time = time_now
294
+ allow(Time).to receive(:now) { time_now }
295
+ allow(op).to receive(:sleep) { |secs| time_now += secs }
296
+
297
+ initial_delay = 10 * MILLIS_PER_SECOND
298
+ delay_multiplier = 1.5
299
+ max_delay = 5 * 60 * MILLIS_PER_SECOND
300
+ total_timeout = 60 * 60 * MILLIS_PER_SECOND
301
+ backoff = BackoffSettings.new(
302
+ initial_delay,
303
+ delay_multiplier,
304
+ max_delay,
305
+ 0,
306
+ 0,
307
+ 0,
308
+ total_timeout
309
+ )
310
+ begin
311
+ op.wait_until_done!(backoff_settings: backoff)
312
+ rescue Google::Gax::RetryError => exc
313
+ expect(exc).to be_a(Google::Gax::RetryError)
314
+ end
315
+ expect(time_now - start_time).to be >= (total_timeout / MILLIS_PER_SECOND)
316
+
317
+ calls_lower_bound = total_timeout / max_delay
318
+ calls_upper_bound = total_timeout / initial_delay
319
+ expect(call_count).to be > calls_lower_bound
320
+ expect(call_count).to be < calls_upper_bound
321
+ end
322
+ end
323
+
324
+ context 'method `on_done`' do
325
+ it 'should yield immediately when the operation is already finished' do
326
+ op = create_op(
327
+ GrpcOp.new(done: true, response: RESULT_ANY, metadata: METADATA_ANY)
328
+ )
329
+ called = false
330
+ op.on_done do |operation|
331
+ expect(operation.results).to eq(RESULT)
332
+ expect(operation.metadata).to eq(METADATA)
333
+ called = true
334
+ end
335
+ expect(called).to eq(true)
336
+ end
337
+ end
338
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: google-gax
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google API Authors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-10-13 00:00:00.000000000 Z
11
+ date: 2017-01-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: googleauth
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 1.3.1
55
+ - !ruby/object:Gem::Dependency
56
+ name: google-protobuf
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 3.0.2
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 3.0.2
55
69
  - !ruby/object:Gem::Dependency
56
70
  name: rly
57
71
  requirement: !ruby/object:Gem::Requirement
@@ -147,15 +161,18 @@ files:
147
161
  - lib/google/gax.rb
148
162
  - lib/google/gax/api_callable.rb
149
163
  - lib/google/gax/bundling.rb
164
+ - lib/google/gax/constants.rb
150
165
  - lib/google/gax/errors.rb
151
166
  - lib/google/gax/grpc.rb
167
+ - lib/google/gax/operation.rb
152
168
  - lib/google/gax/path_template.rb
153
169
  - lib/google/gax/settings.rb
154
170
  - lib/google/gax/version.rb
155
- - lib/google/longrunning/operations_api.rb
171
+ - lib/google/longrunning/operations_client.rb
156
172
  - lib/google/longrunning/operations_client_config.json
157
173
  - spec/google/gax/api_callable_spec.rb
158
174
  - spec/google/gax/bundling_spec.rb
175
+ - spec/google/gax/operation_spec.rb
159
176
  - spec/google/gax/path_template_spec.rb
160
177
  - spec/google/gax/settings_spec.rb
161
178
  - spec/spec_helper.rb
@@ -179,7 +196,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
179
196
  version: '0'
180
197
  requirements: []
181
198
  rubyforge_project:
182
- rubygems_version: 2.5.1
199
+ rubygems_version: 2.4.8
183
200
  signing_key:
184
201
  specification_version: 4
185
202
  summary: Aids the development of APIs for clients and servers based on GRPC and Google