google-gax 0.6.0 → 0.7.0

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.
@@ -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