gapic-common 1.3.0 → 1.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e4338a183319704aa9fb613e73d34b4092a94ad56f3136c2d4a0490a3218770f
4
- data.tar.gz: 3a0d1456f8c2bc573245e5c46afae6b2c83be393085bf6bebc5b28c06368d3f7
3
+ metadata.gz: 6dbc3fc8f2b53d01d228f377851d21d941cedd307a9528e7ba732c5e8d2565e2
4
+ data.tar.gz: d6ded505cf91783149b49373f2efb2ef105860705a22f2940c27f6b27d83be39
5
5
  SHA512:
6
- metadata.gz: 696026e2b9ca26c060c2b65a336f790ec193938a7740d8bdce3008c6bfae40cd80290077b717174554d7e6a1530e470f2523a5859b210c2bf9bd583e7dd72041
7
- data.tar.gz: 42979948486f1e55f990bdbcc0ee2a697ffbf3c450b4013a7ae293e0960291533bfc4356fcfb8cfdeca5eae94d97a7ff522e2b5667cd1e9611de93cf39af560e
6
+ metadata.gz: e7533c44cae4643cec30b87e96fc61750ca2ba2a3458c711788d51987436b25ca3248f6c8d011cf06a00992eec4458e3403ac0b64850a43d153368cd3a6c0203
7
+ data.tar.gz: cd51bd91e418f8d5c71c3f6e484b29f4c420121b14baca686309f074928162f97c0259555bd32d28cb6e747a397c99c0e3d5aeb6cd99085d309ed61482af7cfa
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Release History
2
2
 
3
+ ### 1.4.0 (2026-09-23)
4
+
5
+ #### Features
6
+
7
+ * add custom predicate matching to RetryPolicy ([#59](https://github.com/googleapis/ruby-core-libraries/issues/59))
8
+ #### Bug Fixes
9
+
10
+ * require grpc >= 1.83 for post-quantum key exchange ([#73](https://github.com/googleapis/ruby-core-libraries/issues/73))
11
+ * only use emit_default for proto messages ([#75](https://github.com/googleapis/ruby-core-libraries/issues/75))
12
+
3
13
  ### 1.3.0 (2026-03-05)
4
14
 
5
15
  #### Features
data/README.md CHANGED
@@ -15,7 +15,7 @@ convenient and idiomatic API surface to callers.
15
15
 
16
16
  ## Supported Ruby Versions
17
17
 
18
- This library is supported on Ruby 3.0+.
18
+ This library is supported on Ruby 3.2+.
19
19
 
20
20
  Google provides official support for Ruby versions that are actively supported
21
21
  by Ruby Core—that is, Ruby versions that are either in normal maintenance or in
@@ -24,6 +24,35 @@ work, but are unsupported and not recommended. See
24
24
  https://www.ruby-lang.org/en/downloads/branches/ for details about the Ruby
25
25
  support schedule.
26
26
 
27
+ ## Post-Quantum Key Exchange
28
+
29
+ Clients built on this library negotiate the hybrid post-quantum key exchange
30
+ group `X25519MLKEM768` — classical X25519 paired with ML-KEM-768 ([NIST FIPS
31
+ 203][]) — over TLS 1.3. No application code changes are required, because the
32
+ handshake belongs to the transport layer. The two transports source that
33
+ support differently:
34
+
35
+ | Transport | Cryptographic provider | Requirement | Enforced by this gem? |
36
+ | --- | --- | --- | --- |
37
+ | gRPC | BoringSSL, vendored inside the `grpc` gem | `grpc >= 1.83` | Yes |
38
+ | REST | Host system OpenSSL, via `Net::HTTP` and Faraday | OpenSSL `>= 3.5` | No |
39
+
40
+ gRPC clients get post-quantum key exchange automatically: `gapic-common`
41
+ depends on `grpc >= 1.83`, the first release to offer `X25519MLKEM768` in the
42
+ TLS ClientHello by default.
43
+
44
+ The REST requirement cannot be expressed as a gem dependency. Ruby's `openssl`
45
+ is a default gem bound to whatever `libssl` the host provides, and ML-KEM first
46
+ ships in OpenSSL 3.5. On an older host, REST connections negotiate classical
47
+ X25519 instead — a safe fallback rather than an error, but not post-quantum. To
48
+ check the OpenSSL your Ruby is linked against:
49
+
50
+ ```sh
51
+ ruby -ropenssl -e 'puts OpenSSL::OPENSSL_LIBRARY_VERSION'
52
+ ```
53
+
54
+ [NIST FIPS 203]: https://csrc.nist.gov/pubs/fips/203/final
55
+
27
56
  ## Contributing
28
57
 
29
58
  Contributions to this library are always welcome and highly encouraged.
@@ -45,9 +45,17 @@ module Gapic
45
45
  # @param retry_codes [Array<String|Integer>] List of retry codes.
46
46
  # @param timeout [Numeric] Timeout threshold value in seconds.
47
47
  # @param jitter [Numeric] Random jitter added to the delay in seconds.
48
+ # @param retry_predicate [Proc, nil] The predicate to evaluate whether to retry on a given error. Optional.
49
+ # If the predicate is specified, it is run first. If it returns nil, the decision on
50
+ # whether to retry is made on the basis of retry_codes. Otherwise, the truthiness of
51
+ # the return value determines whether to retry.
48
52
  #
49
- def initialize initial_delay: nil, max_delay: nil, multiplier: nil, retry_codes: nil, timeout: nil, jitter: nil
53
+ def initialize initial_delay: nil, max_delay: nil, multiplier: nil, retry_codes: nil, timeout: nil,
54
+ jitter: nil, retry_predicate: nil
50
55
  raise ArgumentError, "jitter cannot be negative" if jitter&.negative?
56
+ if retry_predicate && !retry_predicate.respond_to?(:call)
57
+ raise ArgumentError, "retry_predicate must respond to :call"
58
+ end
51
59
 
52
60
  # Instance values are set as `nil` to determine whether values are overriden from default.
53
61
  @initial_delay = initial_delay
@@ -56,6 +64,7 @@ module Gapic
56
64
  @retry_codes = convert_codes retry_codes
57
65
  @timeout = timeout
58
66
  @jitter = jitter
67
+ @retry_predicate = retry_predicate
59
68
  start!
60
69
  end
61
70
 
@@ -89,6 +98,19 @@ module Gapic
89
98
  @jitter || DEFAULT_JITTER
90
99
  end
91
100
 
101
+ ##
102
+ # The predicate to evaluate whether to retry on a given error. Optional.
103
+ #
104
+ # When a predicate is specified:
105
+ # 1. The predicate is executed first on the error.
106
+ # 2. If it returns nil, the decision on whether to retry is made on the basis of retry_codes.
107
+ # 3. Otherwise, the truthiness of the return value determines whether to retry.
108
+ #
109
+ # @return [Proc, nil]
110
+ def retry_predicate
111
+ @retry_predicate
112
+ end
113
+
92
114
  ##
93
115
  # Returns a duplicate in a non-executing state, i.e. with the deadline
94
116
  # and current delay reset.
@@ -101,7 +123,8 @@ module Gapic
101
123
  multiplier: @multiplier,
102
124
  retry_codes: @retry_codes,
103
125
  timeout: @timeout,
104
- jitter: @jitter
126
+ jitter: @jitter,
127
+ retry_predicate: @retry_predicate
105
128
  end
106
129
 
107
130
  ##
@@ -176,6 +199,13 @@ module Gapic
176
199
  # @return [Boolean] Whether this error should be retried.
177
200
  #
178
201
  def retry_error? error
202
+ # Run predicate first. If it returns nil, decision is made on the basis of retry_codes.
203
+ # Otherwise return truthiness.
204
+ if @retry_predicate.respond_to? :call
205
+ result = @retry_predicate.call error
206
+ return !!result unless result.nil?
207
+ end
208
+
179
209
  (defined?(::GRPC) && error.is_a?(::GRPC::BadStatus) && retry_codes.include?(error.code)) ||
180
210
  (error.respond_to?(:response_status) &&
181
211
  retry_codes.include?(ErrorCodes.grpc_error_for(error.response_status)))
@@ -197,11 +227,12 @@ module Gapic
197
227
  #
198
228
  def apply_defaults retry_policy
199
229
  return unless retry_policy.is_a? Hash
200
- @retry_codes ||= convert_codes retry_policy[:retry_codes]
201
- @initial_delay ||= retry_policy[:initial_delay]
202
- @multiplier ||= retry_policy[:multiplier]
203
- @max_delay ||= retry_policy[:max_delay]
204
- @jitter ||= retry_policy[:jitter]
230
+ @retry_codes ||= convert_codes retry_policy[:retry_codes]
231
+ @initial_delay ||= retry_policy[:initial_delay]
232
+ @multiplier ||= retry_policy[:multiplier]
233
+ @max_delay ||= retry_policy[:max_delay]
234
+ @jitter ||= retry_policy[:jitter]
235
+ @retry_predicate ||= retry_policy[:retry_predicate]
205
236
 
206
237
  self
207
238
  end
@@ -214,13 +245,14 @@ module Gapic
214
245
  other.multiplier == multiplier &&
215
246
  other.retry_codes == retry_codes &&
216
247
  other.timeout == timeout &&
217
- other.jitter == jitter
248
+ other.jitter == jitter &&
249
+ other.retry_predicate == retry_predicate
218
250
  end
219
251
  alias == eql?
220
252
 
221
253
  # @private Hash code
222
254
  def hash
223
- [initial_delay, max_delay, multiplier, retry_codes, timeout, jitter].hash
255
+ [initial_delay, max_delay, multiplier, retry_codes, timeout, jitter, retry_predicate].hash
224
256
  end
225
257
 
226
258
  private
@@ -14,6 +14,6 @@
14
14
 
15
15
  module Gapic
16
16
  module Common
17
- VERSION = "1.3.0".freeze
17
+ VERSION = "1.4.0".freeze
18
18
  end
19
19
  end
@@ -160,7 +160,16 @@ module Gapic
160
160
  request_body_field = request.send body_template.to_sym if request.respond_to? body_template.to_sym
161
161
  if request_body_field
162
162
  request_hash_without_uri.delete camel_name_for body_template
163
- body = request_body_field.to_json emit_defaults: true
163
+ # `emit_defaults` is only meaningful for, and only accepted by,
164
+ # `Google::Protobuf::MessageExts#to_json`. When the body template points at a
165
+ # scalar, enum or repeated field, `to_json` resolves to the json gem's
166
+ # `Object#to_json`, which has never accepted the keyword: json 2.x silently
167
+ # discarded unknown keywords, json 3.x raises ArgumentError.
168
+ body = if request_body_field.is_a? ::Google::Protobuf::MessageExts
169
+ request_body_field.to_json emit_defaults: true
170
+ else
171
+ request_body_field.to_json
172
+ end
164
173
  end
165
174
 
166
175
  query_params = build_query_params request_hash_without_uri
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gapic-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Google API Authors
@@ -137,16 +137,22 @@ dependencies:
137
137
  name: grpc
138
138
  requirement: !ruby/object:Gem::Requirement
139
139
  requirements:
140
- - - "~>"
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '1.83'
143
+ - - "<"
141
144
  - !ruby/object:Gem::Version
142
- version: '1.66'
145
+ version: 2.a
143
146
  type: :runtime
144
147
  prerelease: false
145
148
  version_requirements: !ruby/object:Gem::Requirement
146
149
  requirements:
147
- - - "~>"
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '1.83'
153
+ - - "<"
148
154
  - !ruby/object:Gem::Version
149
- version: '1.66'
155
+ version: 2.a
150
156
  email:
151
157
  - googleapis-packages@google.com
152
158
  executables: []
@@ -213,7 +219,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
213
219
  requirements:
214
220
  - - ">="
215
221
  - !ruby/object:Gem::Version
216
- version: '3.1'
222
+ version: '3.2'
217
223
  required_rubygems_version: !ruby/object:Gem::Requirement
218
224
  requirements:
219
225
  - - ">="