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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7ed0b03acfdc65e94f59a9de7d9ef17c82d8de2c
|
4
|
+
data.tar.gz: b49bdf5c29d4abea509227477aebe0ad2242ee5d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8fd2ba9b1d30101302aae49b74160fc00d509dd065b20e2416e962a8a28c42008694f67ec30e6cc13ff7dc526bb34b8b2a879857ea5dd584525b34999e8e0de0
|
7
|
+
data.tar.gz: e632150cec07b9861a0ffe258f3d994cb3f047be303acbcae91844f331afbbc37e311b1c47cd540746b3790efddc4e972fd00ce8dee0af54abac2e11e6ab01ae
|
data/lib/google/gax.rb
CHANGED
@@ -28,6 +28,7 @@
|
|
28
28
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
29
29
|
|
30
30
|
require 'google/gax/api_callable'
|
31
|
+
require 'google/gax/constants'
|
31
32
|
require 'google/gax/errors'
|
32
33
|
require 'google/gax/path_template'
|
33
34
|
require 'google/gax/settings'
|
@@ -36,279 +37,5 @@ require 'google/gax/version'
|
|
36
37
|
module Google
|
37
38
|
# Gax defines Google API extensions
|
38
39
|
module Gax
|
39
|
-
# rubocop:disable Metrics/ParameterLists
|
40
|
-
|
41
|
-
# Encapsulates the call settings for an ApiCallable
|
42
|
-
# @!attribute [r] timeout
|
43
|
-
# @return [Numeric]
|
44
|
-
# @!attribute [r] retry_options
|
45
|
-
# @return [RetryOptions]
|
46
|
-
# @!attribute [r] page_descriptor
|
47
|
-
# @return [PageDescriptor]
|
48
|
-
# @!attribute [r] page_token
|
49
|
-
# @return [Object]
|
50
|
-
# @!attribute [r] bundle_descriptor
|
51
|
-
# @return [BundleDescriptor]
|
52
|
-
# @!attribute [r] kwargs
|
53
|
-
# @return [Hash]
|
54
|
-
class CallSettings
|
55
|
-
attr_reader :timeout, :retry_options, :page_descriptor, :page_token,
|
56
|
-
:bundler, :bundle_descriptor, :kwargs, :errors
|
57
|
-
|
58
|
-
# @param timeout [Numeric] The client-side timeout for API calls. This
|
59
|
-
# parameter is ignored for retrying calls.
|
60
|
-
# @param retry_options [RetryOptions] The configuration for retrying upon
|
61
|
-
# transient error. If set to nil, this call will not retry.
|
62
|
-
# @param page_descriptor [PageDescriptor] indicates the structure of page
|
63
|
-
# streaming to be performed. If set to nil, page streaming is not
|
64
|
-
# performed.
|
65
|
-
# @param page_token [Object] determines the page token used in the
|
66
|
-
# page streaming request. If there is no page_descriptor, this has no
|
67
|
-
# meaning.
|
68
|
-
# @param bundler orchestrates bundling. If nil, bundling is not
|
69
|
-
# performed.
|
70
|
-
# @param bundle_descriptor [BundleDescriptor] indicates the structure of
|
71
|
-
# the bundle. If nil, bundling is not performed.
|
72
|
-
# @param kwargs [Hash]
|
73
|
-
# Additional keyword argments to be passed to the API call.
|
74
|
-
# @param errors [Array<Exception>]
|
75
|
-
# Configures the exceptions to wrap with GaxError.
|
76
|
-
def initialize(timeout: 30, retry_options: nil, page_descriptor: nil,
|
77
|
-
page_token: nil, bundler: nil, bundle_descriptor: nil,
|
78
|
-
kwargs: {}, errors: [])
|
79
|
-
@timeout = timeout
|
80
|
-
@retry_options = retry_options
|
81
|
-
@page_descriptor = page_descriptor
|
82
|
-
@page_token = page_token
|
83
|
-
@bundler = bundler
|
84
|
-
@bundle_descriptor = bundle_descriptor
|
85
|
-
@kwargs = kwargs
|
86
|
-
@errors = errors
|
87
|
-
end
|
88
|
-
|
89
|
-
# @return true when it has retry codes.
|
90
|
-
def retry_codes?
|
91
|
-
@retry_options && @retry_options.retry_codes
|
92
|
-
end
|
93
|
-
|
94
|
-
# @return true when it has valid bundler configuration.
|
95
|
-
def bundler?
|
96
|
-
@bundler && @bundle_descriptor
|
97
|
-
end
|
98
|
-
|
99
|
-
# Creates a new CallSetting instance which is based on this but merged
|
100
|
-
# settings from options.
|
101
|
-
# @param options [CallOptions, nil] The overriding call settings.
|
102
|
-
# @return a new merged call settings.
|
103
|
-
def merge(options)
|
104
|
-
unless options
|
105
|
-
return CallSettings.new(timeout: @timeout,
|
106
|
-
retry_options: @retry_options,
|
107
|
-
page_descriptor: @page_descriptor,
|
108
|
-
page_token: @page_token,
|
109
|
-
bundler: @bundler,
|
110
|
-
bundle_descriptor: @bundle_descriptor,
|
111
|
-
kwargs: @kwargs,
|
112
|
-
errors: @errors)
|
113
|
-
end
|
114
|
-
|
115
|
-
timeout = if options.timeout == :OPTION_INHERIT
|
116
|
-
@timeout
|
117
|
-
else
|
118
|
-
options.timeout
|
119
|
-
end
|
120
|
-
retry_options = if options.retry_options == :OPTION_INHERIT
|
121
|
-
@retry_options
|
122
|
-
else
|
123
|
-
options.retry_options
|
124
|
-
end
|
125
|
-
page_token = if options.page_token == :OPTION_INHERIT
|
126
|
-
@page_token
|
127
|
-
else
|
128
|
-
options.page_token
|
129
|
-
end
|
130
|
-
|
131
|
-
kwargs = @kwargs.dup
|
132
|
-
kwargs.update(options.kwargs) if options.kwargs != :OPTION_INHERIT
|
133
|
-
|
134
|
-
CallSettings.new(timeout: timeout,
|
135
|
-
retry_options: retry_options,
|
136
|
-
page_descriptor: @page_descriptor,
|
137
|
-
page_token: page_token,
|
138
|
-
bundler: @bundler,
|
139
|
-
bundle_descriptor: @bundle_descriptor,
|
140
|
-
kwargs: kwargs,
|
141
|
-
errors: @errors)
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
private_constant :CallSettings
|
146
|
-
|
147
|
-
# Encapsulates the overridable settings for a particular API call
|
148
|
-
# @!attribute [r] timeout
|
149
|
-
# @return [Numeric, :OPTION_INHERIT]
|
150
|
-
# @!attribute [r] retry_options
|
151
|
-
# @return [RetryOptions, :OPTION_INHERIT]
|
152
|
-
# @!attribute [r] page_token
|
153
|
-
# @return [Object, :OPTION_INHERIT, :INITIAL_PAGE]
|
154
|
-
# @!attribute [r] kwargs
|
155
|
-
# @return [Hash, :OPTION_INHERIT]
|
156
|
-
class CallOptions
|
157
|
-
attr_reader :timeout, :retry_options, :page_token, :kwargs
|
158
|
-
|
159
|
-
# @param timeout [Numeric, :OPTION_INHERIT]
|
160
|
-
# The client-side timeout for API calls.
|
161
|
-
# @param retry_options [RetryOptions, :OPTION_INHERIT]
|
162
|
-
# The configuration for retrying upon transient error.
|
163
|
-
# If set to nil, this call will not retry.
|
164
|
-
# @param page_token [Object, :OPTION_INHERIT]
|
165
|
-
# If set and the call is configured for page streaming, page streaming
|
166
|
-
# is starting with this page_token.
|
167
|
-
# @param kwargs [Hash, :OPTION_INHERIT]
|
168
|
-
# Additional keyword argments to be passed to the API call.
|
169
|
-
def initialize(timeout: :OPTION_INHERIT,
|
170
|
-
retry_options: :OPTION_INHERIT,
|
171
|
-
page_token: :OPTION_INHERIT,
|
172
|
-
kwargs: :OPTION_INHERIT)
|
173
|
-
@timeout = timeout
|
174
|
-
@retry_options = retry_options
|
175
|
-
@page_token = page_token
|
176
|
-
@kwargs = kwargs
|
177
|
-
end
|
178
|
-
end
|
179
|
-
|
180
|
-
# Describes the structure of a page-streaming call.
|
181
|
-
class PageDescriptor < Struct.new(:request_page_token_field,
|
182
|
-
:response_page_token_field,
|
183
|
-
:resource_field)
|
184
|
-
end
|
185
|
-
|
186
|
-
# Per-call configurable settings for retrying upon transient failure.
|
187
|
-
class RetryOptions < Struct.new(:retry_codes, :backoff_settings)
|
188
|
-
# @!attribute retry_codes
|
189
|
-
# @return [Array<Grpc::Code>] a list of exceptions upon which
|
190
|
-
# a retry should be attempted.
|
191
|
-
# @!attribute backoff_settings
|
192
|
-
# @return [BackoffSettings] configuring the retry exponential
|
193
|
-
# backoff algorithm.
|
194
|
-
end
|
195
|
-
|
196
|
-
# Parameters to the exponential backoff algorithm for retrying.
|
197
|
-
class BackoffSettings < Struct.new(
|
198
|
-
:initial_retry_delay_millis,
|
199
|
-
:retry_delay_multiplier,
|
200
|
-
:max_retry_delay_millis,
|
201
|
-
:initial_rpc_timeout_millis,
|
202
|
-
:rpc_timeout_multiplier,
|
203
|
-
:max_rpc_timeout_millis,
|
204
|
-
:total_timeout_millis
|
205
|
-
)
|
206
|
-
# @!attribute initial_retry_delay_millis
|
207
|
-
# @return [Numeric] the initial delay time, in milliseconds,
|
208
|
-
# between the completion of the first failed request and the
|
209
|
-
# initiation of the first retrying request.
|
210
|
-
# @!attribute retry_delay_multiplier
|
211
|
-
# @return [Numeric] the multiplier by which to increase the
|
212
|
-
# delay time between the completion of failed requests, and
|
213
|
-
# the initiation of the subsequent retrying request.
|
214
|
-
# @!attribute max_retry_delay_millis
|
215
|
-
# @return [Numeric] the maximum delay time, in milliseconds,
|
216
|
-
# between requests. When this value is reached,
|
217
|
-
# +retry_delay_multiplier+ will no longer be used to
|
218
|
-
# increase delay time.
|
219
|
-
# @!attribute initial_rpc_timeout_millis
|
220
|
-
# @return [Numeric] the initial timeout parameter to the request.
|
221
|
-
# @!attribute rpc_timeout_multiplier
|
222
|
-
# @return [Numeric] the multiplier by which to increase the
|
223
|
-
# timeout parameter between failed requests.
|
224
|
-
# @!attribute max_rpc_timeout_millis
|
225
|
-
# @return [Numeric] the maximum timeout parameter, in
|
226
|
-
# milliseconds, for a request. When this value is reached,
|
227
|
-
# +rpc_timeout_multiplier+ will no longer be used to
|
228
|
-
# increase the timeout.
|
229
|
-
# @!attribute total_timeout_millis
|
230
|
-
# @return [Numeric] the total time, in milliseconds, starting
|
231
|
-
# from when the initial request is sent, after which an
|
232
|
-
# error will be returned, regardless of the retrying
|
233
|
-
# attempts made meanwhile.
|
234
|
-
end
|
235
|
-
|
236
|
-
# Describes the structure of bundled call.
|
237
|
-
#
|
238
|
-
# request_discriminator_fields may include '.' as a separator, which is
|
239
|
-
# used to indicate object traversal. This allows fields in nested objects
|
240
|
-
# to be used to determine what requests to bundle.
|
241
|
-
class BundleDescriptor < Struct.new(:bundled_field,
|
242
|
-
:request_discriminator_fields,
|
243
|
-
:subresponse_field)
|
244
|
-
# @!attribute bundled_field
|
245
|
-
# @return [String] the repeated field in the request message
|
246
|
-
# that will have its elements aggregated by bundling.
|
247
|
-
# @!attribute request_discriminator_fields
|
248
|
-
# @return [Array<String>] a list of fields in the target
|
249
|
-
# request message class that are used to determine which
|
250
|
-
# messages should be bundled together.
|
251
|
-
# @!attribute subresponse_field
|
252
|
-
# @return [String] an optional field, when present it
|
253
|
-
# indicates the field in the response message that should be
|
254
|
-
# used to demultiplex the response into multiple response
|
255
|
-
# messages.
|
256
|
-
def initialize(bundled_field, request_discriminator_fields,
|
257
|
-
subresponse_field: nil)
|
258
|
-
super(bundled_field, request_discriminator_fields, subresponse_field)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
|
-
# Holds values used to configure bundling.
|
263
|
-
#
|
264
|
-
# The xxx_threshold attributes are used to configure when the bundled
|
265
|
-
# request should be made.
|
266
|
-
class BundleOptions < Struct.new(:element_count_threshold,
|
267
|
-
:element_count_limit,
|
268
|
-
:request_byte_threshold,
|
269
|
-
:request_byte_limit,
|
270
|
-
:delay_threshold_millis)
|
271
|
-
# @!attribute element_count_threshold
|
272
|
-
# @return [Numeric] the bundled request will be sent once the
|
273
|
-
# count of outstanding elements in the repeated field
|
274
|
-
# reaches this value.
|
275
|
-
# @!attribute element_count_limit
|
276
|
-
# @return [Numeric] represents a hard limit on the number of
|
277
|
-
# elements in the repeated field of the bundle; if adding a
|
278
|
-
# request to a bundle would exceed this value, the bundle is
|
279
|
-
# sent and the new request is added to a fresh bundle. It is
|
280
|
-
# invalid for a single request to exceed this limit.
|
281
|
-
# @!attribute request_byte_threshold
|
282
|
-
# @return [Numeric] the bundled request will be sent once the
|
283
|
-
# count of bytes in the request reaches this value. Note
|
284
|
-
# that this value is pessimistically approximated by summing
|
285
|
-
# the bytesizes of the elements in the repeated field, and
|
286
|
-
# therefore may be an under-approximation.
|
287
|
-
# @!attribute request_byte_limit
|
288
|
-
# @return [Numeric] represents a hard limit on the size of the
|
289
|
-
# bundled request; if adding a request to a bundle would
|
290
|
-
# exceed this value, the bundle is sent and the new request
|
291
|
-
# is added to a fresh bundle. It is invalid for a single
|
292
|
-
# request to exceed this limit. Note that this value is
|
293
|
-
# pessimistically approximated by summing the bytesizes of
|
294
|
-
# the elements in the repeated field, with a buffer applied
|
295
|
-
# to correspond to the resulting under-approximation.
|
296
|
-
# @!attribute delay_threshold_millis
|
297
|
-
# @return [Numeric] the bundled request will be sent this
|
298
|
-
# amount of time after the first element in the bundle was
|
299
|
-
# added to it.
|
300
|
-
def initialize(element_count_threshold: 0,
|
301
|
-
element_count_limit: 0,
|
302
|
-
request_byte_threshold: 0,
|
303
|
-
request_byte_limit: 0,
|
304
|
-
delay_threshold_millis: 0)
|
305
|
-
super(
|
306
|
-
element_count_threshold,
|
307
|
-
element_count_limit,
|
308
|
-
request_byte_threshold,
|
309
|
-
request_byte_limit,
|
310
|
-
delay_threshold_millis)
|
311
|
-
end
|
312
|
-
end
|
313
40
|
end
|
314
41
|
end
|
@@ -36,8 +36,6 @@ require 'google/gax/bundling'
|
|
36
36
|
|
37
37
|
module Google
|
38
38
|
module Gax
|
39
|
-
MILLIS_PER_SECOND = 1000.0
|
40
|
-
|
41
39
|
# A class to provide the Enumerable interface for page-streaming method.
|
42
40
|
# PagedEnumerable assumes that the API call returns a message for a page
|
43
41
|
# which holds a list of resources and the token to the next page.
|
@@ -341,7 +339,6 @@ module Google
|
|
341
339
|
result = nil
|
342
340
|
now = Time.now
|
343
341
|
deadline = now + total_timeout
|
344
|
-
|
345
342
|
loop do
|
346
343
|
begin
|
347
344
|
result = add_timeout_arg(a_func, timeout, kwargs).call(request)
|
data/lib/google/gax/bundling.rb
CHANGED
@@ -116,7 +116,7 @@ module Google
|
|
116
116
|
# The number of bundled elements in the repeated field.
|
117
117
|
# @return [Numeric]
|
118
118
|
def element_count
|
119
|
-
@inputs.reduce(0) { |
|
119
|
+
@inputs.reduce(0) { |acc, elem| acc + elem.count }
|
120
120
|
end
|
121
121
|
|
122
122
|
# The size of the request in bytes of the bundled field elements.
|
@@ -0,0 +1,34 @@
|
|
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
|
+
module Google
|
31
|
+
module Gax
|
32
|
+
MILLIS_PER_SECOND = 1000.0
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,253 @@
|
|
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
|
+
# These must be loaded separate from google/gax to avoid circular dependency.
|
33
|
+
require 'google/gax/constants'
|
34
|
+
require 'google/gax/settings'
|
35
|
+
|
36
|
+
module Google
|
37
|
+
module Gax
|
38
|
+
# A class used to wrap Google::Longrunning::Operation objects. This class
|
39
|
+
# provides helper methods to check the status of an Operation
|
40
|
+
#
|
41
|
+
# @example Checking Operation status
|
42
|
+
# require 'google/gax/operation'
|
43
|
+
# require 'google/longrunning/operations_client'
|
44
|
+
#
|
45
|
+
# operations_client = Google::Longrunning::OperationsClient.new
|
46
|
+
# op = Google::Gax::Operation.new(
|
47
|
+
# api.methodThatReturnsOperation(),
|
48
|
+
# operations_client,
|
49
|
+
# Google::Example::ResultType,
|
50
|
+
# Google::Example::MetadataType
|
51
|
+
# )
|
52
|
+
#
|
53
|
+
# op.done? # => false
|
54
|
+
# op.reload! # => operation completed
|
55
|
+
#
|
56
|
+
# if op.done?
|
57
|
+
# results = op.results
|
58
|
+
# handle_error(results) if op.error?
|
59
|
+
# # Handle results.
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# @example Working with callbacks
|
63
|
+
# require 'google/gax/operation'
|
64
|
+
# require 'google/longrunning/operations_client'
|
65
|
+
#
|
66
|
+
# operations_client = Google::Longrunning::OperationsClient.new
|
67
|
+
# op = Google::Gax::Operation.new(
|
68
|
+
# api.method_that_returns_operation,
|
69
|
+
# operations_client,
|
70
|
+
# Google::Example::ResultType,
|
71
|
+
# Google::Example::MetadataType
|
72
|
+
# )
|
73
|
+
#
|
74
|
+
# # Register a callback to be run when an operation is done.
|
75
|
+
# op.on_done do |operation|
|
76
|
+
# raise operation.results.message if operation.error?
|
77
|
+
# # process(operation.results)
|
78
|
+
# # process(operation.metadata)
|
79
|
+
# end
|
80
|
+
#
|
81
|
+
# # Reload the operation running callbacks if operation completed.
|
82
|
+
# op.reload!
|
83
|
+
#
|
84
|
+
# # Or block until the operation completes, passing a block to be called
|
85
|
+
# # on completion.
|
86
|
+
# op.wait_until_done do |operation|
|
87
|
+
# raise operation.results.message if operation.error?
|
88
|
+
# # process(operation.results)
|
89
|
+
# # process(operation.rmetadata)
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# @attribute [r] grpc_op
|
93
|
+
# @return [Google::Longrunning::Operation] The wrapped grpc
|
94
|
+
# operation object.
|
95
|
+
# @attribute [rw] call_options
|
96
|
+
# @return [Google::Gax::CallOptions] The call options used when reloading
|
97
|
+
# the operation.
|
98
|
+
class Operation
|
99
|
+
attr_reader :grpc_op
|
100
|
+
|
101
|
+
attr_accessor :call_options
|
102
|
+
|
103
|
+
# @param grpc_op [Google::Longrunning::Operation]
|
104
|
+
# The inital longrunning operation.
|
105
|
+
# @param client [Google::Longrunning::OperationsClient]
|
106
|
+
# The client that handles the grpc operations.
|
107
|
+
# @param result_type [Class] The class type to be unpacked from the
|
108
|
+
# result.
|
109
|
+
# @param metadata_type [Class] The class type to be unpacked from the
|
110
|
+
# metadata.
|
111
|
+
# @param call_options [Google::Gax::CallOptions]
|
112
|
+
# The call options that are used when reloading the operation.
|
113
|
+
def initialize(grpc_op, client, result_type, metadata_type,
|
114
|
+
call_options: nil)
|
115
|
+
@grpc_op = grpc_op
|
116
|
+
@client = client
|
117
|
+
@call_options = call_options
|
118
|
+
@result_type = result_type
|
119
|
+
@metadata_type = metadata_type
|
120
|
+
@callbacks = []
|
121
|
+
end
|
122
|
+
|
123
|
+
# If the operation is done, returns the result, otherwise returns nil.
|
124
|
+
# If the operation response is an error, the error will be returned.
|
125
|
+
# If a type is provided, the response will be unpacked using the type
|
126
|
+
# provided; returning nil if the response is not of the type provided.
|
127
|
+
# If the type is not of provided, the response will be unpacked using
|
128
|
+
# the response's type_url if the type_url is found in the
|
129
|
+
# Google::Protobuf::DescriptorPool.generated_pool.
|
130
|
+
# If the type cannot be found the raw response is retuned.
|
131
|
+
#
|
132
|
+
# @return [Object, Google::Rpc::Status, nil]
|
133
|
+
# The result of the operation. If it is an error a Google::Rpc::Status
|
134
|
+
# will be returned.
|
135
|
+
def results
|
136
|
+
return nil unless done?
|
137
|
+
return @grpc_op.error if error?
|
138
|
+
unpack(@grpc_op.response, @result_type)
|
139
|
+
end
|
140
|
+
|
141
|
+
# Returns the metadata of an operation. If a type is provided,
|
142
|
+
# the metadata will be unpacked using the type provided; returning nil
|
143
|
+
# if the metadata is not of the type provided.
|
144
|
+
# If the type is not of provided, the metadata will be unpacked using
|
145
|
+
# the metadata's type_url if the type_url is found in the
|
146
|
+
# Google::Protobuf::DescriptorPool.generated_pool.
|
147
|
+
# If the type cannot be found the raw metadata is retuned.
|
148
|
+
#
|
149
|
+
# @return [Object, nil]
|
150
|
+
# The metadata of the operation. Can be nil.
|
151
|
+
def metadata
|
152
|
+
return nil if @grpc_op.metadata.nil?
|
153
|
+
unpack(@grpc_op.metadata, @metadata_type)
|
154
|
+
end
|
155
|
+
|
156
|
+
# Checks if the operation is done. This does not send a new api call,
|
157
|
+
# but checks the result of the previous api call to see if done.
|
158
|
+
#
|
159
|
+
# @return [Boolean] Whether the operation is done.
|
160
|
+
def done?
|
161
|
+
@grpc_op.done
|
162
|
+
end
|
163
|
+
|
164
|
+
# Checks if the operation is done and the result is an error.
|
165
|
+
# If the operation is not finished then this will return false.
|
166
|
+
#
|
167
|
+
# @return [Boolean] Whether an error has been returned.
|
168
|
+
def error?
|
169
|
+
done? ? @grpc_op.result == :error : false
|
170
|
+
end
|
171
|
+
|
172
|
+
# Cancels the operation.
|
173
|
+
def cancel
|
174
|
+
@client.cancel_operation(@grpc_op.name)
|
175
|
+
end
|
176
|
+
|
177
|
+
# Reloads the operation object.
|
178
|
+
#
|
179
|
+
# @return [Google::Gax::Operation]
|
180
|
+
# Since this method changes internal state, it returns itself.
|
181
|
+
def reload!
|
182
|
+
@grpc_op = @client.get_operation(@grpc_op.name, options: @call_options)
|
183
|
+
if done?
|
184
|
+
@callbacks.each { |proc| proc.call(self) }
|
185
|
+
@callbacks.clear
|
186
|
+
end
|
187
|
+
self
|
188
|
+
end
|
189
|
+
alias refresh! reload!
|
190
|
+
|
191
|
+
# Blocking method to wait until the operation has completed or the
|
192
|
+
# maximum timeout has been reached. Upon completion, registered callbacks
|
193
|
+
# will be called, then - if a block is given - the block will be called.
|
194
|
+
#
|
195
|
+
# @param backoff_settings [Google::Gax::BackoffSettings]
|
196
|
+
# The backoff settings used to manipulate how this method retries
|
197
|
+
# checking if the operation is done.
|
198
|
+
# @yield operation [Google::Gax::Operation] Yields the finished Operation.
|
199
|
+
def wait_until_done!(backoff_settings: nil)
|
200
|
+
unless backoff_settings
|
201
|
+
backoff_settings = BackoffSettings.new(
|
202
|
+
10 * MILLIS_PER_SECOND,
|
203
|
+
1.3,
|
204
|
+
5 * 60 * MILLIS_PER_SECOND,
|
205
|
+
0,
|
206
|
+
0,
|
207
|
+
0,
|
208
|
+
60 * 60 * MILLIS_PER_SECOND
|
209
|
+
)
|
210
|
+
end
|
211
|
+
|
212
|
+
delay = backoff_settings.initial_retry_delay_millis / MILLIS_PER_SECOND
|
213
|
+
max_delay = backoff_settings.max_retry_delay_millis / MILLIS_PER_SECOND
|
214
|
+
delay_multiplier = backoff_settings.retry_delay_multiplier
|
215
|
+
total_timeout =
|
216
|
+
backoff_settings.total_timeout_millis / MILLIS_PER_SECOND
|
217
|
+
deadline = Time.now + total_timeout
|
218
|
+
until done?
|
219
|
+
sleep(delay)
|
220
|
+
if Time.now >= deadline
|
221
|
+
raise RetryError, 'Retry total timeout exceeded with exception'
|
222
|
+
end
|
223
|
+
delay = [delay * delay_multiplier, max_delay].min
|
224
|
+
reload!
|
225
|
+
end
|
226
|
+
yield(self) if block_given?
|
227
|
+
end
|
228
|
+
|
229
|
+
# Registers a callback to be run when a refreshed operation is marked
|
230
|
+
# as done. If the operation has completed prior to a call to this function
|
231
|
+
# the callback will be called instead of registered.
|
232
|
+
#
|
233
|
+
# @yield operation [Google::Gax::Operation] Yields the finished Operation.
|
234
|
+
def on_done(&block)
|
235
|
+
if done?
|
236
|
+
yield(self)
|
237
|
+
else
|
238
|
+
@callbacks.push(block)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
# TODO: This is from google/protobuf/well_known_types.rb.
|
243
|
+
# Using google/protobuf in gax-ruby is currently causing a dependency
|
244
|
+
# conflict with grpc. When grpc depends on google-protobuf v3.1.0
|
245
|
+
# remove this function and use Google::Protobuf::Any#unpack.
|
246
|
+
def unpack(any_pb, klass)
|
247
|
+
type_name = any_pb.type_url.split('/')[-1]
|
248
|
+
return klass.decode(any_pb.value) if type_name == klass.descriptor.name
|
249
|
+
end
|
250
|
+
private :unpack
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|