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.
- checksums.yaml +4 -4
- data/lib/google/gax.rb +1 -274
- data/lib/google/gax/api_callable.rb +0 -3
- data/lib/google/gax/bundling.rb +1 -1
- data/lib/google/gax/constants.rb +34 -0
- data/lib/google/gax/operation.rb +253 -0
- data/lib/google/gax/path_template.rb +3 -2
- data/lib/google/gax/settings.rb +275 -2
- data/lib/google/gax/version.rb +1 -1
- data/lib/google/longrunning/{operations_api.rb → operations_client.rb} +34 -53
- data/spec/google/gax/operation_spec.rb +338 -0
- metadata +21 -4
@@ -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.
|
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:
|
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/
|
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.
|
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
|