gapic-common 1.4.0 → 1.5.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/CHANGELOG.md +15 -0
- data/README.md +2 -5
- data/lib/gapic/common/retry_policy.rb +34 -0
- data/lib/gapic/common/version.rb +1 -1
- data/lib/gapic/logging_concerns.rb +4 -0
- data/lib/gapic/rest/client_stub.rb +13 -3
- data/lib/gapic/rest/error.rb +4 -1
- data/lib/gapic/rest/grpc_transcoder.rb +39 -0
- data/lib/gapic/rest/resumable_upload/core.rb +77 -0
- data/lib/gapic/rest/resumable_upload/data_types.rb +428 -0
- data/lib/gapic/rest/resumable_upload/driver/abridge.rb +168 -0
- data/lib/gapic/rest/resumable_upload/driver/retry_decider.rb +190 -0
- data/lib/gapic/rest/resumable_upload/driver/upload_log.rb +343 -0
- data/lib/gapic/rest/resumable_upload/driver.rb +855 -0
- data/lib/gapic/rest/resumable_upload/errors.rb +581 -0
- data/lib/gapic/rest/resumable_upload/events.rb +129 -0
- data/lib/gapic/rest/resumable_upload/instructions.rb +273 -0
- data/lib/gapic/rest/resumable_upload/retry_policies.rb +116 -0
- data/lib/gapic/rest/resumable_upload/rules.rb +1210 -0
- data/lib/gapic/rest/resumable_upload.rb +110 -0
- data/lib/gapic/rest.rb +2 -0
- data/lib/gapic/resumable_upload.rb +508 -0
- metadata +14 -1
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 Google LLC
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
require "gapic/common/error"
|
|
18
|
+
require "gapic/rest/error"
|
|
19
|
+
|
|
20
|
+
module Gapic
|
|
21
|
+
module Rest
|
|
22
|
+
module ResumableUpload
|
|
23
|
+
##
|
|
24
|
+
# @private
|
|
25
|
+
# HTTP status code to reason phrase mapping.
|
|
26
|
+
#
|
|
27
|
+
# Includes `200` because a well-formed success can still be a protocol failure: an
|
|
28
|
+
# `X-Goog-Upload-Status` that does not match the phase of the request in flight is reported as a
|
|
29
|
+
# {BadResponseError} carrying the 200 it arrived with.
|
|
30
|
+
#
|
|
31
|
+
# @return [Hash<Integer, String>]
|
|
32
|
+
HTTP_STATUS_PHRASES = {
|
|
33
|
+
200 => "OK",
|
|
34
|
+
400 => "Bad Request",
|
|
35
|
+
401 => "Unauthorized",
|
|
36
|
+
403 => "Forbidden",
|
|
37
|
+
404 => "Not Found",
|
|
38
|
+
405 => "Method Not Allowed",
|
|
39
|
+
408 => "Request Timeout",
|
|
40
|
+
409 => "Conflict",
|
|
41
|
+
410 => "Gone",
|
|
42
|
+
411 => "Length Required",
|
|
43
|
+
412 => "Precondition Failed",
|
|
44
|
+
413 => "Payload Too Large",
|
|
45
|
+
415 => "Unsupported Media Type",
|
|
46
|
+
416 => "Range Not Satisfiable",
|
|
47
|
+
429 => "Too Many Requests",
|
|
48
|
+
499 => "Client Closed Request",
|
|
49
|
+
500 => "Internal Server Error",
|
|
50
|
+
502 => "Bad Gateway",
|
|
51
|
+
503 => "Service Unavailable",
|
|
52
|
+
504 => "Gateway Timeout"
|
|
53
|
+
}.freeze
|
|
54
|
+
|
|
55
|
+
##
|
|
56
|
+
# @private
|
|
57
|
+
# Internal formatting helper for terminal error message and attribute extraction.
|
|
58
|
+
#
|
|
59
|
+
module ErrorBuilder
|
|
60
|
+
class << self
|
|
61
|
+
##
|
|
62
|
+
# @private
|
|
63
|
+
# Formats status representation.
|
|
64
|
+
#
|
|
65
|
+
# @param status [Object, nil] Status value
|
|
66
|
+
# @return [String, nil]
|
|
67
|
+
def format_status status
|
|
68
|
+
return nil if status.nil? || status.to_s.empty?
|
|
69
|
+
|
|
70
|
+
status.to_s
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
##
|
|
74
|
+
# @private
|
|
75
|
+
# Strips REST error prefix from message string.
|
|
76
|
+
#
|
|
77
|
+
# @param raw_message [String, nil] Raw error message
|
|
78
|
+
# @return [String, nil]
|
|
79
|
+
def clean_message raw_message
|
|
80
|
+
return nil if raw_message.nil? || raw_message.empty?
|
|
81
|
+
|
|
82
|
+
prefix = Gapic::Rest::Error::REST_ERROR_PREFIX
|
|
83
|
+
msg = raw_message.to_s
|
|
84
|
+
msg = msg.sub(/\A#{Regexp.escape prefix}:\s*/, "") if msg.start_with? prefix
|
|
85
|
+
msg = msg.sub(/\A:\s*/, "").strip
|
|
86
|
+
msg.empty? ? nil : msg
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
##
|
|
90
|
+
# @private
|
|
91
|
+
# Builds error attributes tuple from an HTTP event or wrapped error.
|
|
92
|
+
#
|
|
93
|
+
# @param event [Object] HTTP response event or failure event
|
|
94
|
+
# @param prefix [String] Error message prefix
|
|
95
|
+
# @return [Array] Tuple of [message, status_code, status, details, headers]
|
|
96
|
+
def build_attributes event, prefix: "Resumable upload failed"
|
|
97
|
+
if event.respond_to?(:error) && event.error
|
|
98
|
+
build_from_wrapped_error event, prefix: prefix
|
|
99
|
+
else
|
|
100
|
+
build_from_http_event event, prefix: prefix
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
private
|
|
105
|
+
|
|
106
|
+
##
|
|
107
|
+
# @private
|
|
108
|
+
# Builds error attributes when a wrapped REST error is available.
|
|
109
|
+
#
|
|
110
|
+
# @param event [Object] HTTP response event containing wrapped error
|
|
111
|
+
# @param prefix [String] Error message prefix
|
|
112
|
+
# @return [Array] Tuple of [message, status_code, status, details, headers]
|
|
113
|
+
def build_from_wrapped_error event, prefix:
|
|
114
|
+
err = event.error
|
|
115
|
+
status_code = err.status_code || (event.respond_to?(:status) ? event.status : nil)
|
|
116
|
+
status = err.status
|
|
117
|
+
status_name = format_status(status) || HTTP_STATUS_PHRASES[status_code]
|
|
118
|
+
status_part = status_name ? " #{status_name}" : ""
|
|
119
|
+
inner_msg = clean_message err.message
|
|
120
|
+
msg = if inner_msg
|
|
121
|
+
"#{prefix} with HTTP #{status_code}#{status_part}: #{inner_msg}"
|
|
122
|
+
else
|
|
123
|
+
"#{prefix} with HTTP #{status_code}#{status_part}"
|
|
124
|
+
end
|
|
125
|
+
headers = err.headers || (event.respond_to?(:headers) ? event.headers : nil)
|
|
126
|
+
[msg, status_code, status, err.details, headers]
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
##
|
|
130
|
+
# @private
|
|
131
|
+
# Builds error attributes directly from raw HTTP response event.
|
|
132
|
+
#
|
|
133
|
+
# @param event [Object] HTTP response event
|
|
134
|
+
# @param prefix [String] Error message prefix
|
|
135
|
+
# @return [Array] Tuple of [message, status_code, status, details, headers]
|
|
136
|
+
def build_from_http_event event, prefix:
|
|
137
|
+
status_code = event.status
|
|
138
|
+
headers = event.respond_to?(:headers) && event.headers ? event.headers : {}
|
|
139
|
+
upload_status = headers["x-goog-upload-status"] || headers["X-Goog-Upload-Status"]
|
|
140
|
+
status_desc = upload_status ? "'#{upload_status}'" : "missing"
|
|
141
|
+
status_name = HTTP_STATUS_PHRASES[status_code]
|
|
142
|
+
status_part = status_name ? " #{status_name}" : ""
|
|
143
|
+
msg = "#{prefix} with HTTP #{status_code}#{status_part} " \
|
|
144
|
+
"(X-Goog-Upload-Status: #{status_desc})"
|
|
145
|
+
[msg, status_code, nil, nil, headers]
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
##
|
|
151
|
+
# Mixin providing {ResumeHandle} access and uniform formatting for resumable errors.
|
|
152
|
+
#
|
|
153
|
+
# Every error that may carry a resume handle includes this module, so it doubles as the rescue target
|
|
154
|
+
# for "this upload failed but can be retried from where it stopped":
|
|
155
|
+
#
|
|
156
|
+
# @example
|
|
157
|
+
# begin
|
|
158
|
+
# upload.start stream: io, upload_size: size
|
|
159
|
+
# rescue Gapic::Rest::ResumableUpload::HasResumeHandle => e
|
|
160
|
+
# retry_later e.resume_handle if e.resume_handle
|
|
161
|
+
# raise
|
|
162
|
+
# end
|
|
163
|
+
#
|
|
164
|
+
# Included by {RequestFailedError}, {DeadlineExceededError}, {BadResponseError},
|
|
165
|
+
# {UnseekableStreamError} and {StreamMismatchError}.
|
|
166
|
+
#
|
|
167
|
+
# Deliberately **not** included by {UploadRejectedError}, {UploadCancelledError} or {SessionStateError}:
|
|
168
|
+
# the first two mean the session is permanently terminated on the server and the third is a caller misuse,
|
|
169
|
+
# so none of them is retryable. Note also that `resume_handle` may still be `nil` on an including error,
|
|
170
|
+
# for instance when the failure happened before initiation established an upload URL.
|
|
171
|
+
#
|
|
172
|
+
# @!attribute [r] resume_handle
|
|
173
|
+
# @return [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated upload session resume handle
|
|
174
|
+
#
|
|
175
|
+
module HasResumeHandle
|
|
176
|
+
# @return [Gapic::Rest::ResumableUpload::ResumeHandle, nil]
|
|
177
|
+
attr_reader :resume_handle
|
|
178
|
+
|
|
179
|
+
##
|
|
180
|
+
# @private
|
|
181
|
+
# Suffix appended to error message when a resume handle is present.
|
|
182
|
+
# @return [String]
|
|
183
|
+
RESUMABLE_SUFFIX = " (upload session is resumable: see #resume_handle)"
|
|
184
|
+
|
|
185
|
+
##
|
|
186
|
+
# @private
|
|
187
|
+
# Appends the uniform resumable suffix if resume_handle is non-nil.
|
|
188
|
+
#
|
|
189
|
+
# @param message [String, nil] Error message
|
|
190
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Resume handle
|
|
191
|
+
# @return [String, nil]
|
|
192
|
+
def self.append_suffix message, resume_handle
|
|
193
|
+
return message if resume_handle.nil?
|
|
194
|
+
return RESUMABLE_SUFFIX.strip if message.nil? || message.to_s.strip.empty?
|
|
195
|
+
return message if message.end_with? RESUMABLE_SUFFIX
|
|
196
|
+
|
|
197
|
+
"#{message}#{RESUMABLE_SUFFIX}"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
##
|
|
202
|
+
# @private
|
|
203
|
+
# Raised when an internal state machine or driver invariant is violated.
|
|
204
|
+
# Produced by {Rules} when an unlisted shape or recipe is encountered, and by
|
|
205
|
+
# {Driver} when a recipe emits a malformed instruction batch.
|
|
206
|
+
#
|
|
207
|
+
class InternalError < Gapic::Common::Error
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
##
|
|
211
|
+
# @private
|
|
212
|
+
# Raised when an invalid or unmatched event is dispatched for the current protocol state.
|
|
213
|
+
#
|
|
214
|
+
# @!attribute [r] response
|
|
215
|
+
# @return [Gapic::Rest::ResumableUpload::Event::HttpResponse, Object, nil] Associated HTTP response
|
|
216
|
+
# @!attribute [r] state
|
|
217
|
+
# @return [Symbol, nil] Current protocol state
|
|
218
|
+
# @!attribute [r] event
|
|
219
|
+
# @return [Object, nil] Received event
|
|
220
|
+
#
|
|
221
|
+
class InvalidTransitionError < InternalError
|
|
222
|
+
# @return [Gapic::Rest::ResumableUpload::Event::HttpResponse, Object, nil]
|
|
223
|
+
attr_reader :response
|
|
224
|
+
|
|
225
|
+
# @return [Symbol, nil] Current protocol state
|
|
226
|
+
attr_reader :state
|
|
227
|
+
|
|
228
|
+
# @return [Object, nil] Received event
|
|
229
|
+
attr_reader :event
|
|
230
|
+
|
|
231
|
+
##
|
|
232
|
+
# Initializes a new InvalidTransitionError.
|
|
233
|
+
#
|
|
234
|
+
# @param message [String] Descriptive error message
|
|
235
|
+
# @param state [Symbol, nil] Current protocol state
|
|
236
|
+
# @param event [Object, nil] Received event
|
|
237
|
+
# @param response [Gapic::Rest::ResumableUpload::Event::HttpResponse, Object, nil] Associated HTTP response
|
|
238
|
+
def initialize message, state: nil, event: nil, response: nil
|
|
239
|
+
@state = state
|
|
240
|
+
@event = event
|
|
241
|
+
@response = response || (event if defined?(Event::HttpResponse) && event.is_a?(Event::HttpResponse))
|
|
242
|
+
super message
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
##
|
|
246
|
+
# Creates an InvalidTransitionError from an event.
|
|
247
|
+
#
|
|
248
|
+
# @param event [Object] Received event
|
|
249
|
+
# @param state [Symbol, nil] Current protocol state
|
|
250
|
+
# @param message [String, nil] Descriptive error message
|
|
251
|
+
# @param response [Object, nil] Associated HTTP response
|
|
252
|
+
# @return [InvalidTransitionError]
|
|
253
|
+
def self.from event, state: nil, message: nil, response: nil
|
|
254
|
+
new(
|
|
255
|
+
message || "Invalid transition for event #{event.inspect}",
|
|
256
|
+
state: state,
|
|
257
|
+
event: event,
|
|
258
|
+
response: response
|
|
259
|
+
)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
##
|
|
264
|
+
# Raised when stream rewinding is required but the stream does not support seeking.
|
|
265
|
+
#
|
|
266
|
+
# @!attribute [r] resume_handle
|
|
267
|
+
# @return [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
268
|
+
#
|
|
269
|
+
class UnseekableStreamError < Gapic::Common::Error
|
|
270
|
+
include HasResumeHandle
|
|
271
|
+
|
|
272
|
+
##
|
|
273
|
+
# Initializes a new UnseekableStreamError.
|
|
274
|
+
#
|
|
275
|
+
# @param message [String, nil] Descriptive error message
|
|
276
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
277
|
+
def initialize message = nil, resume_handle: nil
|
|
278
|
+
@resume_handle = resume_handle
|
|
279
|
+
super HasResumeHandle.append_suffix(message, resume_handle)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
##
|
|
283
|
+
# @private
|
|
284
|
+
# Creates an UnseekableStreamError with optional resume handle.
|
|
285
|
+
#
|
|
286
|
+
# @param message [String, nil] Descriptive error message
|
|
287
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
288
|
+
# @return [UnseekableStreamError]
|
|
289
|
+
def self.from message = nil, resume_handle: nil
|
|
290
|
+
new message, resume_handle: resume_handle
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
##
|
|
295
|
+
# Raised when stream content or length does not match resumed upload specifications.
|
|
296
|
+
#
|
|
297
|
+
# @!attribute [r] resume_handle
|
|
298
|
+
# @return [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
299
|
+
#
|
|
300
|
+
class StreamMismatchError < Gapic::Common::Error
|
|
301
|
+
include HasResumeHandle
|
|
302
|
+
|
|
303
|
+
##
|
|
304
|
+
# Initializes a new StreamMismatchError.
|
|
305
|
+
#
|
|
306
|
+
# @param message [String] Error message
|
|
307
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
308
|
+
def initialize message = "Stream content or length does not match resumed upload", resume_handle: nil
|
|
309
|
+
@resume_handle = resume_handle
|
|
310
|
+
super HasResumeHandle.append_suffix(message, resume_handle)
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
##
|
|
314
|
+
# @private
|
|
315
|
+
# Creates a StreamMismatchError with optional resume handle.
|
|
316
|
+
#
|
|
317
|
+
# @param message [String, nil] Error message
|
|
318
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
319
|
+
# @return [StreamMismatchError]
|
|
320
|
+
def self.from message = nil, resume_handle: nil
|
|
321
|
+
msg = message || "Stream content or length does not match resumed upload"
|
|
322
|
+
new msg, resume_handle: resume_handle
|
|
323
|
+
end
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
##
|
|
327
|
+
# Raised when an unrecoverable HTTP response is received.
|
|
328
|
+
#
|
|
329
|
+
# @!attribute [r] response_body
|
|
330
|
+
# @return [String, nil] Response body from backend
|
|
331
|
+
# @!attribute [r] resume_handle
|
|
332
|
+
# @return [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
333
|
+
#
|
|
334
|
+
class BadResponseError < Gapic::Rest::Error
|
|
335
|
+
include HasResumeHandle
|
|
336
|
+
|
|
337
|
+
# @return [String, nil] Response body from backend
|
|
338
|
+
attr_reader :response_body
|
|
339
|
+
|
|
340
|
+
##
|
|
341
|
+
# Initializes a new BadResponseError.
|
|
342
|
+
#
|
|
343
|
+
# @param message [String, nil] Error message
|
|
344
|
+
# @param status_code [Integer, nil] HTTP status code
|
|
345
|
+
# @param status [String, nil] Status description
|
|
346
|
+
# @param details [Object, nil] Error details
|
|
347
|
+
# @param headers [Object, nil] Response headers
|
|
348
|
+
# @param response_body [String, nil] Response body
|
|
349
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
350
|
+
def initialize message = nil, status_code = nil, status: nil, details: nil, headers: nil,
|
|
351
|
+
response_body: nil, resume_handle: nil
|
|
352
|
+
@response_body = response_body
|
|
353
|
+
@resume_handle = resume_handle
|
|
354
|
+
super HasResumeHandle.append_suffix(message, resume_handle),
|
|
355
|
+
status_code, status: status, details: details, headers: headers
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
##
|
|
359
|
+
# @private
|
|
360
|
+
# Creates a BadResponseError from an HTTP response event.
|
|
361
|
+
#
|
|
362
|
+
# @param event [Object] HTTP response event
|
|
363
|
+
# @param response_body [String, nil] Optional response body override
|
|
364
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Optional resume handle
|
|
365
|
+
# @param prefix [String] Leading clause of the error message, used to name the protocol phase the
|
|
366
|
+
# response arrived in
|
|
367
|
+
# @return [BadResponseError]
|
|
368
|
+
def self.from event, response_body: nil, resume_handle: nil, prefix: "Resumable upload failed"
|
|
369
|
+
body = response_body || (event.respond_to?(:body) ? event.body : nil)
|
|
370
|
+
message, status_code, status, details, headers = ErrorBuilder.build_attributes event, prefix: prefix
|
|
371
|
+
new message, status_code, status: status, details: details, headers: headers,
|
|
372
|
+
response_body: body, resume_handle: resume_handle
|
|
373
|
+
end
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
##
|
|
377
|
+
# Raised when the resumable upload backend explicitly rejects the
|
|
378
|
+
# upload session (returns non-2xx with X-Goog-Upload-Status: final).
|
|
379
|
+
#
|
|
380
|
+
# @!attribute [r] response_body
|
|
381
|
+
# @return [String, nil] Response body from backend
|
|
382
|
+
#
|
|
383
|
+
class UploadRejectedError < Gapic::Rest::Error
|
|
384
|
+
# @return [String, nil] Response body from backend
|
|
385
|
+
attr_reader :response_body
|
|
386
|
+
|
|
387
|
+
##
|
|
388
|
+
# Initializes a new UploadRejectedError.
|
|
389
|
+
#
|
|
390
|
+
# @param message [String, nil] Error message
|
|
391
|
+
# @param status_code [Integer, nil] HTTP status code
|
|
392
|
+
# @param status [String, nil] Status description
|
|
393
|
+
# @param details [Object, nil] Error details
|
|
394
|
+
# @param headers [Object, nil] Response headers
|
|
395
|
+
# @param response_body [String, nil] Response body
|
|
396
|
+
def initialize message = nil, status_code = nil, status: nil, details: nil, headers: nil, response_body: nil
|
|
397
|
+
@response_body = response_body
|
|
398
|
+
super message, status_code, status: status, details: details, headers: headers
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
##
|
|
402
|
+
# @private
|
|
403
|
+
# Creates an UploadRejectedError from an HTTP response event.
|
|
404
|
+
#
|
|
405
|
+
# @param event [Object] HTTP response event
|
|
406
|
+
# @param response_body [String, nil] Optional response body override
|
|
407
|
+
# @return [UploadRejectedError]
|
|
408
|
+
def self.from event, response_body: nil
|
|
409
|
+
body = response_body || (event.respond_to?(:body) ? event.body : nil)
|
|
410
|
+
message, status_code, status, details, headers =
|
|
411
|
+
ErrorBuilder.build_attributes event, prefix: "Upload rejected by server"
|
|
412
|
+
new message, status_code, status: status, details: details, headers: headers, response_body: body
|
|
413
|
+
end
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
##
|
|
417
|
+
# Raised when the upload session was cancelled and will accept no further data.
|
|
418
|
+
#
|
|
419
|
+
# Reachable today only for a cancellation this client did not request: the server reports an
|
|
420
|
+
# established session as cancelled while a chunk, a finalize, or a recovery query is in flight,
|
|
421
|
+
# because another process, another client, or a server-side policy ended it. Client-initiated
|
|
422
|
+
# cancellation is not part of the public API yet, and this error is also what that will raise.
|
|
423
|
+
#
|
|
424
|
+
# Deliberately does not include {HasResumeHandle}. A cancelled session is gone server-side, so there
|
|
425
|
+
# is nothing to resume and retrying against it cannot succeed; a new upload must be started instead.
|
|
426
|
+
#
|
|
427
|
+
class UploadCancelledError < Gapic::Common::Error
|
|
428
|
+
##
|
|
429
|
+
# Initializes a new UploadCancelledError.
|
|
430
|
+
#
|
|
431
|
+
# @param message [String] Cancellation message
|
|
432
|
+
def initialize message = "Upload session was cancelled"
|
|
433
|
+
super message
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
##
|
|
437
|
+
# @private
|
|
438
|
+
# Creates an UploadCancelledError from a source event or message string.
|
|
439
|
+
#
|
|
440
|
+
# @param source [Object, String, nil] Source event or message
|
|
441
|
+
# @return [UploadCancelledError]
|
|
442
|
+
def self.from source = nil
|
|
443
|
+
if source.is_a?(String) && !source.empty?
|
|
444
|
+
new source
|
|
445
|
+
else
|
|
446
|
+
new
|
|
447
|
+
end
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
##
|
|
452
|
+
# Raised when an upload exceeds its global monotonic deadline.
|
|
453
|
+
#
|
|
454
|
+
# @!attribute [r] root_cause
|
|
455
|
+
# @return [Object, nil] Root cause exception if deadline exceeded during a retry loop
|
|
456
|
+
# @!attribute [r] resume_handle
|
|
457
|
+
# @return [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
458
|
+
#
|
|
459
|
+
class DeadlineExceededError < Gapic::Common::Error
|
|
460
|
+
include HasResumeHandle
|
|
461
|
+
|
|
462
|
+
# @return [Object, nil] Root cause exception if deadline exceeded during a retry loop
|
|
463
|
+
attr_reader :root_cause
|
|
464
|
+
|
|
465
|
+
##
|
|
466
|
+
# Initializes a new DeadlineExceededError.
|
|
467
|
+
#
|
|
468
|
+
# @param message [String] Deadline exceeded message
|
|
469
|
+
# @param root_cause [Object, nil] Root cause exception
|
|
470
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
471
|
+
def initialize message = "Upload deadline exceeded", root_cause: nil, resume_handle: nil
|
|
472
|
+
super HasResumeHandle.append_suffix(message, resume_handle)
|
|
473
|
+
@root_cause = root_cause
|
|
474
|
+
@resume_handle = resume_handle
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
##
|
|
478
|
+
# @private
|
|
479
|
+
# Creates a DeadlineExceededError with optional resume handle.
|
|
480
|
+
#
|
|
481
|
+
# @param message [String, nil] Deadline exceeded message
|
|
482
|
+
# @param root_cause [Object, nil] Root cause exception
|
|
483
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
484
|
+
# @return [DeadlineExceededError]
|
|
485
|
+
def self.from message = "Upload deadline exceeded", root_cause: nil, resume_handle: nil
|
|
486
|
+
new message, root_cause: root_cause, resume_handle: resume_handle
|
|
487
|
+
end
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
##
|
|
491
|
+
# Raised when an HTTP request fails (e.g. transport connection failure, request timeout, or retries exhausted).
|
|
492
|
+
#
|
|
493
|
+
# @!attribute [r] cause
|
|
494
|
+
# @return [StandardError, nil] Underlying cause exception
|
|
495
|
+
# @!attribute [r] resume_handle
|
|
496
|
+
# @return [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
497
|
+
# @!attribute [r] status_code
|
|
498
|
+
# @return [Integer, nil] HTTP status code if cause was a REST error
|
|
499
|
+
# @!attribute [r] status
|
|
500
|
+
# @return [String, nil] Status description if cause was a REST error
|
|
501
|
+
# @!attribute [r] details
|
|
502
|
+
# @return [Object, nil] Error details if cause was a REST error
|
|
503
|
+
# @!attribute [r] headers
|
|
504
|
+
# @return [Object, nil] Response headers if cause was a REST error
|
|
505
|
+
#
|
|
506
|
+
class RequestFailedError < Gapic::Common::Error
|
|
507
|
+
include HasResumeHandle
|
|
508
|
+
|
|
509
|
+
# @return [Integer, nil]
|
|
510
|
+
attr_reader :status_code
|
|
511
|
+
|
|
512
|
+
# @return [String, nil]
|
|
513
|
+
attr_reader :status
|
|
514
|
+
|
|
515
|
+
# @return [Object, nil]
|
|
516
|
+
attr_reader :details
|
|
517
|
+
|
|
518
|
+
# @return [Object, nil]
|
|
519
|
+
attr_reader :headers
|
|
520
|
+
|
|
521
|
+
##
|
|
522
|
+
# Initializes a new RequestFailedError.
|
|
523
|
+
#
|
|
524
|
+
# @param message [String, nil] Error message
|
|
525
|
+
# @param cause [StandardError, nil] Underlying cause exception
|
|
526
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
527
|
+
# @param status_code [Integer, nil] HTTP status code
|
|
528
|
+
# @param status [String, nil] Status description
|
|
529
|
+
# @param details [Object, nil] Error details
|
|
530
|
+
# @param headers [Object, nil] Response headers
|
|
531
|
+
def initialize message = nil, cause: nil, resume_handle: nil,
|
|
532
|
+
status_code: nil, status: nil, details: nil, headers: nil
|
|
533
|
+
@cause = cause
|
|
534
|
+
@resume_handle = resume_handle
|
|
535
|
+
@status_code = status_code || (cause.respond_to?(:status_code) ? cause.status_code : nil)
|
|
536
|
+
@status = status || (cause.respond_to?(:status) ? cause.status : nil)
|
|
537
|
+
@details = details || (cause.respond_to?(:details) ? cause.details : nil)
|
|
538
|
+
@headers = headers || (cause.respond_to?(:headers) ? cause.headers : nil)
|
|
539
|
+
msg = message || cause&.message || "Request failed"
|
|
540
|
+
super HasResumeHandle.append_suffix(msg, resume_handle)
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
##
|
|
544
|
+
# Returns the underlying cause exception.
|
|
545
|
+
#
|
|
546
|
+
# @return [StandardError, nil]
|
|
547
|
+
def cause
|
|
548
|
+
@cause || super
|
|
549
|
+
end
|
|
550
|
+
|
|
551
|
+
##
|
|
552
|
+
# @private
|
|
553
|
+
# Creates a RequestFailedError from a failure event or error.
|
|
554
|
+
#
|
|
555
|
+
# @param event_or_error [Event::RequestFailed, StandardError] Source event or error
|
|
556
|
+
# @param message [String, nil] Optional message override
|
|
557
|
+
# @param resume_handle [Gapic::Rest::ResumableUpload::ResumeHandle, nil] Associated resume handle
|
|
558
|
+
# @return [RequestFailedError]
|
|
559
|
+
def self.from event_or_error, message: nil, resume_handle: nil
|
|
560
|
+
if event_or_error.respond_to? :source_error
|
|
561
|
+
cause = event_or_error.source_error
|
|
562
|
+
msg = message || event_or_error.message || cause&.message || "Request failed"
|
|
563
|
+
new msg, cause: cause, resume_handle: resume_handle
|
|
564
|
+
elsif event_or_error.is_a? Exception
|
|
565
|
+
msg = message || event_or_error.message || "Request failed"
|
|
566
|
+
new msg, cause: event_or_error, resume_handle: resume_handle
|
|
567
|
+
else
|
|
568
|
+
new message || event_or_error.to_s, resume_handle: resume_handle
|
|
569
|
+
end
|
|
570
|
+
end
|
|
571
|
+
end
|
|
572
|
+
|
|
573
|
+
##
|
|
574
|
+
# Raised when an operation violates the upload session lifecycle rules, e.g. starting a second run
|
|
575
|
+
# on a coordinator while one is still in flight.
|
|
576
|
+
#
|
|
577
|
+
class SessionStateError < Gapic::Common::Error
|
|
578
|
+
end
|
|
579
|
+
end
|
|
580
|
+
end
|
|
581
|
+
end
|