gapic-common 1.4.1 → 1.5.1
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 +5 -3
- 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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3906b246e3ecacee83c366fee3cd10077a56a72b29c3490ca8ff01ac4e124d65
|
|
4
|
+
data.tar.gz: c0a72cf00fa758234a196d385f53303d41c82cd895a17a339b185b7db529cf3b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 4aaff885138cd52a4f822ebb51af2f2c658700e7ba71d3b1199ada4c3871343e16cb66c1fc65a44606cf178316a07bb61f553a40bcf1ffd80e98a00758e18d51
|
|
7
|
+
data.tar.gz: 59232d7d58c9711b6e0e9e0b1da7ca3f0d69abbda9d10d4fa72412e463d8a57062a45f46131c5c24a392cbbc5e8e99be63b7491c4bcf668f77ed48b4e44a235f
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Release History
|
|
2
2
|
|
|
3
|
+
### 1.5.1 (2026-09-30)
|
|
4
|
+
|
|
5
|
+
#### Bug Fixes
|
|
6
|
+
|
|
7
|
+
* tighten path template matching in the REST transcoder ([#83](https://github.com/googleapis/ruby-core-libraries/issues/83))
|
|
8
|
+
|
|
9
|
+
### 1.5.0 (2026-09-29)
|
|
10
|
+
|
|
11
|
+
#### Features
|
|
12
|
+
|
|
13
|
+
* Resumable Media Upload functionality implementation ([#72](https://github.com/googleapis/ruby-core-libraries/issues/72))
|
|
14
|
+
#### Documentation
|
|
15
|
+
|
|
16
|
+
* remove stale preview notice and disclaimer from READMEs ([#77](https://github.com/googleapis/ruby-core-libraries/issues/77))
|
|
17
|
+
|
|
3
18
|
### 1.4.1 (2026-09-28)
|
|
4
19
|
|
|
5
20
|
#### Bug Fixes
|
data/README.md
CHANGED
|
@@ -61,9 +61,6 @@ See the {file:CONTRIBUTING.md CONTRIBUTING} documentation for more information o
|
|
|
61
61
|
|
|
62
62
|
## Versioning
|
|
63
63
|
|
|
64
|
-
This library
|
|
65
|
-
involved and let us know if you find it useful and we'll work towards a stable version.
|
|
64
|
+
This library follows [Semantic Versioning](http://semver.org/).
|
|
66
65
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
This is not an official Google product.
|
|
66
|
+
This library is considered to be stable and will not have backwards-incompatible changes introduced in subsequent minor releases.
|
|
@@ -19,6 +19,12 @@ module Gapic
|
|
|
19
19
|
##
|
|
20
20
|
# Gapic Common retry policy base class.
|
|
21
21
|
#
|
|
22
|
+
# A policy distinguishes "set to this value" from "never set". Every setting is stored as `nil`
|
|
23
|
+
# until someone supplies it, and the reader for each substitutes the corresponding `DEFAULT_`
|
|
24
|
+
# constant on the way out, so a reader can never say which of the two happened. That distinction is
|
|
25
|
+
# what lets {#apply_defaults} fill in gaps without overwriting a caller's choices, and {#overrides}
|
|
26
|
+
# report what a caller actually asked for.
|
|
27
|
+
#
|
|
22
28
|
class RetryPolicy
|
|
23
29
|
# @return [Numeric] Default initial delay in seconds.
|
|
24
30
|
DEFAULT_INITIAL_DELAY = 1
|
|
@@ -111,6 +117,34 @@ module Gapic
|
|
|
111
117
|
@retry_predicate
|
|
112
118
|
end
|
|
113
119
|
|
|
120
|
+
##
|
|
121
|
+
# @private
|
|
122
|
+
# The settings this policy actually carries, as keyword arguments for {RetryPolicy.initialize}.
|
|
123
|
+
#
|
|
124
|
+
# A key is present only if that setting was explicitly supplied; a key that was never set is
|
|
125
|
+
# absent rather than `nil`. This is what the readers cannot tell you — {#max_delay} returns
|
|
126
|
+
# {DEFAULT_MAX_DELAY} whether the caller chose that number or said nothing — so it is the only
|
|
127
|
+
# safe way to carry one policy's settings onto another without dragging defaults along, and
|
|
128
|
+
# without mistaking a deliberate choice that happens to equal a default for silence.
|
|
129
|
+
#
|
|
130
|
+
# An empty `retry_codes` list counts as unset. It retries nothing, which is exactly what an
|
|
131
|
+
# unset list does, so there is nothing for it to carry.
|
|
132
|
+
#
|
|
133
|
+
# @return [Hash{Symbol=>Object}] Explicitly set settings only
|
|
134
|
+
def overrides
|
|
135
|
+
# Assigns nil, and so omits the key, when the list is absent or empty.
|
|
136
|
+
retry_codes = @retry_codes unless @retry_codes.nil? || @retry_codes.empty?
|
|
137
|
+
{
|
|
138
|
+
initial_delay: @initial_delay,
|
|
139
|
+
max_delay: @max_delay,
|
|
140
|
+
multiplier: @multiplier,
|
|
141
|
+
retry_codes: retry_codes,
|
|
142
|
+
timeout: @timeout,
|
|
143
|
+
jitter: @jitter,
|
|
144
|
+
retry_predicate: @retry_predicate
|
|
145
|
+
}.compact
|
|
146
|
+
end
|
|
147
|
+
|
|
114
148
|
##
|
|
115
149
|
# Returns a duplicate in a non-executing state, i.e. with the deadline
|
|
116
150
|
# and current delay reset.
|
data/lib/gapic/common/version.rb
CHANGED
|
@@ -287,17 +287,27 @@ module Gapic
|
|
|
287
287
|
entry.set "requestId", request_id
|
|
288
288
|
entry.message = "Sending request to #{entry.service}.#{method_name} (try #{try_number})"
|
|
289
289
|
end
|
|
290
|
-
|
|
290
|
+
body_str = body.to_s
|
|
291
291
|
metadata = metadata.to_h rescue {}
|
|
292
|
-
return if
|
|
292
|
+
return if body_str.empty? && metadata.empty?
|
|
293
293
|
stub_logger.debug do |entry|
|
|
294
294
|
entry.set "requestId", request_id
|
|
295
|
-
entry.set "request",
|
|
295
|
+
entry.set "request", abridge_request_body(body_str)
|
|
296
296
|
entry.set "headers", metadata
|
|
297
297
|
entry.message = "(request payload as JSON)"
|
|
298
298
|
end
|
|
299
299
|
end
|
|
300
300
|
|
|
301
|
+
def abridge_request_body body_str
|
|
302
|
+
utf8_body = body_str.dup.force_encoding Encoding::UTF_8
|
|
303
|
+
if body_str.bytesize > 1024 || !utf8_body.valid_encoding?
|
|
304
|
+
prefix_hex = body_str.byteslice(0, 32).unpack1 "H*"
|
|
305
|
+
"<#{body_str.bytesize} bytes, first 32: #{prefix_hex}>"
|
|
306
|
+
else
|
|
307
|
+
utf8_body
|
|
308
|
+
end
|
|
309
|
+
end
|
|
310
|
+
|
|
301
311
|
def log_response method_name, request_id, try_number, response, is_server_streaming
|
|
302
312
|
return unless stub_logger&.enabled?
|
|
303
313
|
stub_logger.info do |entry|
|
data/lib/gapic/rest/error.rb
CHANGED
|
@@ -22,6 +22,9 @@ module Gapic
|
|
|
22
22
|
module Rest
|
|
23
23
|
# Gapic REST exception class
|
|
24
24
|
class Error < ::Gapic::Common::Error
|
|
25
|
+
# @private
|
|
26
|
+
REST_ERROR_PREFIX = "An error has occurred when making a REST request".freeze
|
|
27
|
+
|
|
25
28
|
# @return [Integer, nil] the http status code for the error
|
|
26
29
|
attr_reader :status_code
|
|
27
30
|
# @return [Object, nil] the text representation of status as parsed from the response body
|
|
@@ -79,7 +82,7 @@ module Gapic
|
|
|
79
82
|
|
|
80
83
|
if err.response_body
|
|
81
84
|
msg, code, status, details = try_parse_from_body err.response_body
|
|
82
|
-
message = "
|
|
85
|
+
message = "#{REST_ERROR_PREFIX}: #{msg}" unless msg.nil?
|
|
83
86
|
status_code = code unless code.nil?
|
|
84
87
|
end
|
|
85
88
|
|
|
@@ -111,7 +111,7 @@ module Gapic
|
|
|
111
111
|
# @return [Hash{String, String}]
|
|
112
112
|
# Name to value hash of the variables for the uri template expansion.
|
|
113
113
|
# The values are percent-escaped with slashes potentially preserved.
|
|
114
|
-
# @raise [Gapic::Common::Error] If any parameter value fails path traversal
|
|
114
|
+
# @raise [Gapic::Common::Error] If any parameter value fails path traversal validation.
|
|
115
115
|
def bind_uri_values! http_binding, request_hash
|
|
116
116
|
http_binding.field_bindings.to_h do |field_binding|
|
|
117
117
|
field_path_camel = field_binding.field_path.split(".").map { |part| camel_name_for part }.join(".")
|
|
@@ -252,7 +252,7 @@ module Gapic
|
|
|
252
252
|
# Returns nil if:
|
|
253
253
|
# - the field is not found
|
|
254
254
|
# - the field is a Message or an array,
|
|
255
|
-
# - the regex does not match
|
|
255
|
+
# - the regex does not match the entire string representation
|
|
256
256
|
# @param request_hash [Hash]
|
|
257
257
|
# A hash of the GRPC request or the sub-request with the unset
|
|
258
258
|
# proto3_optional fields removed.
|
|
@@ -266,7 +266,9 @@ module Gapic
|
|
|
266
266
|
|
|
267
267
|
# Covers the case where in `foo.bar.baz`, `baz` is still a submessage or an array.
|
|
268
268
|
return nil if value.is_a?(::Hash) || value.is_a?(::Array)
|
|
269
|
-
|
|
269
|
+
str = value.to_s
|
|
270
|
+
match = regex.match str
|
|
271
|
+
str if match && match.pre_match.empty? && match.post_match.empty?
|
|
270
272
|
end
|
|
271
273
|
|
|
272
274
|
# Finds a value in the hash by path.
|
|
@@ -0,0 +1,77 @@
|
|
|
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/rest/resumable_upload/data_types"
|
|
18
|
+
require "gapic/rest/resumable_upload/rules"
|
|
19
|
+
|
|
20
|
+
module Gapic
|
|
21
|
+
module Rest
|
|
22
|
+
module ResumableUpload
|
|
23
|
+
##
|
|
24
|
+
# @private
|
|
25
|
+
# State machine container holding the immutable State snapshot.
|
|
26
|
+
# Contains zero protocol branching logic and zero side-effects.
|
|
27
|
+
#
|
|
28
|
+
# The middle tier of the three-tier design: `Driver` executes side effects, {Rules} decides transitions,
|
|
29
|
+
# and Core holds the {State} between the two. See {Rules} for the protocol narrative and state graph, and
|
|
30
|
+
# `design/resumable_upload/implementation-guide.md` section 1 for the tier boundaries.
|
|
31
|
+
#
|
|
32
|
+
class Core
|
|
33
|
+
# @private
|
|
34
|
+
# @return [State] Current immutable state snapshot
|
|
35
|
+
attr_reader :state
|
|
36
|
+
|
|
37
|
+
# @private
|
|
38
|
+
# @return [Decision, nil] Decision emitted during the last dispatch
|
|
39
|
+
attr_reader :last_decision
|
|
40
|
+
|
|
41
|
+
##
|
|
42
|
+
# @private
|
|
43
|
+
# Initializes a Core state machine container.
|
|
44
|
+
#
|
|
45
|
+
# @param config [StartUploadConfig, ResumeUploadConfig] Upload session configuration
|
|
46
|
+
#
|
|
47
|
+
def initialize config
|
|
48
|
+
@config = config
|
|
49
|
+
@last_decision = nil
|
|
50
|
+
@state = State.new(
|
|
51
|
+
status: :initializing,
|
|
52
|
+
upload_url: nil,
|
|
53
|
+
offset: 0,
|
|
54
|
+
chunk_size: config.chunk_size || Rules::DEFAULT_CHUNK_SIZE,
|
|
55
|
+
chunk_granularity: nil,
|
|
56
|
+
in_flight_length: 0,
|
|
57
|
+
last_error: nil
|
|
58
|
+
)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
##
|
|
62
|
+
# @private
|
|
63
|
+
# Dispatches event to Rules and updates internal state snapshot.
|
|
64
|
+
#
|
|
65
|
+
# @param event [Object] Input event
|
|
66
|
+
# @return [Array<Object>] Driver instructions
|
|
67
|
+
#
|
|
68
|
+
def dispatch event
|
|
69
|
+
decision = Rules.decide @state, event, @config
|
|
70
|
+
@state = decision.next_state
|
|
71
|
+
@last_decision = decision
|
|
72
|
+
decision.instructions
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|