gapic-common 0.14.0 → 0.15.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 +6 -0
- data/lib/gapic/call_options/error_codes.rb +71 -0
- data/lib/gapic/call_options/retry_policy.rb +6 -30
- data/lib/gapic/call_options.rb +1 -0
- data/lib/gapic/common/version.rb +1 -1
- data/lib/gapic/rest/client_stub.rb +62 -6
- data/lib/gapic/rest/grpc_transcoder/http_binding.rb +54 -1
- data/lib/gapic/rest/grpc_transcoder.rb +5 -30
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5902b53f0f5a46b4682ff855fb89a6a3162af38523fa273f273abeeeed0d3a3d
|
4
|
+
data.tar.gz: a1e9bb69d31725768f00b152efcaf29042657fbb304c2ba2f25de485831fe187
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 84d77cc3d943714b8a3578ecabf3fea3a321dfe0929ee108233d4dcd8fede90a37be21a81e121142739aa3dca102ffff0826a003906bec16f03749beddf59ab2
|
7
|
+
data.tar.gz: 27e2815be724399a4c01ca1d47c7b2e9291ee4583018251f45a2a0162f1d5cd8298d0ca3b8a4cf90fc4ba6f2e410240439e61a22a66fbeae89c5a3e9dc223879
|
data/CHANGELOG.md
CHANGED
@@ -0,0 +1,71 @@
|
|
1
|
+
# Copyright 2019 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
module Gapic
|
16
|
+
class CallOptions
|
17
|
+
##
|
18
|
+
# @private
|
19
|
+
# The gRPC error codes and their HTTP mapping
|
20
|
+
#
|
21
|
+
module ErrorCodes
|
22
|
+
# @private
|
23
|
+
# See https://grpc.github.io/grpc/core/md_doc_statuscodes.html for a
|
24
|
+
# list of error codes.
|
25
|
+
error_code_mapping = [
|
26
|
+
"OK",
|
27
|
+
"CANCELLED",
|
28
|
+
"UNKNOWN",
|
29
|
+
"INVALID_ARGUMENT",
|
30
|
+
"DEADLINE_EXCEEDED",
|
31
|
+
"NOT_FOUND",
|
32
|
+
"ALREADY_EXISTS",
|
33
|
+
"PERMISSION_DENIED",
|
34
|
+
"RESOURCE_EXHAUSTED",
|
35
|
+
"FAILED_PRECONDITION",
|
36
|
+
"ABORTED",
|
37
|
+
"OUT_OF_RANGE",
|
38
|
+
"UNIMPLEMENTED",
|
39
|
+
"INTERNAL",
|
40
|
+
"UNAVAILABLE",
|
41
|
+
"DATA_LOSS",
|
42
|
+
"UNAUTHENTICATED"
|
43
|
+
].freeze
|
44
|
+
|
45
|
+
# @private
|
46
|
+
ERROR_STRING_MAPPING = error_code_mapping.each_with_index.to_h.freeze
|
47
|
+
|
48
|
+
# @private
|
49
|
+
# Converts http error codes into corresponding gRPC ones
|
50
|
+
def self.grpc_error_for http_error_code
|
51
|
+
return 2 unless http_error_code
|
52
|
+
|
53
|
+
# The http status codes mapped to their error classes.
|
54
|
+
{
|
55
|
+
400 => 3, # InvalidArgumentError
|
56
|
+
401 => 16, # UnauthenticatedError
|
57
|
+
403 => 7, # PermissionDeniedError
|
58
|
+
404 => 5, # NotFoundError
|
59
|
+
409 => 6, # AlreadyExistsError
|
60
|
+
412 => 9, # FailedPreconditionError
|
61
|
+
429 => 8, # ResourceExhaustedError
|
62
|
+
499 => 1, # CanceledError
|
63
|
+
500 => 13, # InternalError
|
64
|
+
501 => 12, # UnimplementedError
|
65
|
+
503 => 14, # UnavailableError
|
66
|
+
504 => 4 # DeadlineExceededError
|
67
|
+
}[http_error_code] || 2 # UnknownError
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -12,6 +12,8 @@
|
|
12
12
|
# See the License for the specific language governing permissions and
|
13
13
|
# limitations under the License.
|
14
14
|
|
15
|
+
require "gapic/call_options/error_codes"
|
16
|
+
|
15
17
|
module Gapic
|
16
18
|
class CallOptions
|
17
19
|
##
|
@@ -101,38 +103,12 @@ module Gapic
|
|
101
103
|
[retry_codes, initial_delay, multiplier, max_delay].hash
|
102
104
|
end
|
103
105
|
|
104
|
-
# @private
|
105
|
-
# See https://grpc.github.io/grpc/core/md_doc_statuscodes.html for a
|
106
|
-
# list of error codes.
|
107
|
-
ERROR_CODE_MAPPING = [
|
108
|
-
"OK",
|
109
|
-
"CANCELLED",
|
110
|
-
"UNKNOWN",
|
111
|
-
"INVALID_ARGUMENT",
|
112
|
-
"DEADLINE_EXCEEDED",
|
113
|
-
"NOT_FOUND",
|
114
|
-
"ALREADY_EXISTS",
|
115
|
-
"PERMISSION_DENIED",
|
116
|
-
"RESOURCE_EXHAUSTED",
|
117
|
-
"FAILED_PRECONDITION",
|
118
|
-
"ABORTED",
|
119
|
-
"OUT_OF_RANGE",
|
120
|
-
"UNIMPLEMENTED",
|
121
|
-
"INTERNAL",
|
122
|
-
"UNAVAILABLE",
|
123
|
-
"DATA_LOSS",
|
124
|
-
"UNAUTHENTICATED"
|
125
|
-
].freeze
|
126
|
-
|
127
|
-
# @private
|
128
|
-
ERROR_STRING_MAPPING = ERROR_CODE_MAPPING.each_with_index.each_with_object({}) do |(str, num), hash|
|
129
|
-
hash[str] = num
|
130
|
-
end.freeze
|
131
|
-
|
132
106
|
private
|
133
107
|
|
134
108
|
def retry? error
|
135
|
-
error.is_a?(::GRPC::BadStatus) && retry_codes.include?(error.code)
|
109
|
+
(error.is_a?(::GRPC::BadStatus) && retry_codes.include?(error.code)) ||
|
110
|
+
(error.respond_to?(:response_status) &&
|
111
|
+
retry_codes.include?(ErrorCodes.grpc_error_for(error.response_status)))
|
136
112
|
end
|
137
113
|
|
138
114
|
def delay!
|
@@ -145,7 +121,7 @@ module Gapic
|
|
145
121
|
Array(input_codes).map do |obj|
|
146
122
|
case obj
|
147
123
|
when String
|
148
|
-
ERROR_STRING_MAPPING[obj]
|
124
|
+
ErrorCodes::ERROR_STRING_MAPPING[obj]
|
149
125
|
when Integer
|
150
126
|
obj
|
151
127
|
end
|
data/lib/gapic/call_options.rb
CHANGED
data/lib/gapic/common/version.rb
CHANGED
@@ -125,21 +125,65 @@ module Gapic
|
|
125
125
|
# @param uri [String] uri to send this request to
|
126
126
|
# @param body [String, nil] a body to send with the request, nil for requests without a body
|
127
127
|
# @param params [Hash] query string parameters for the request
|
128
|
-
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied
|
129
|
-
#
|
128
|
+
# @param options [::Gapic::CallOptions,Hash] gapic options to be applied to the REST call.
|
129
|
+
# @param is_server_streaming [Boolean] flag if method is streaming
|
130
|
+
# @yieldparam chunk [String] The chunk of data received during server streaming.
|
131
|
+
# @return [Faraday::Response]
|
132
|
+
def make_http_request verb, uri:, body:, params:, options:, is_server_streaming: false, &block
|
133
|
+
# Converts hash and nil to an options object
|
134
|
+
options = ::Gapic::CallOptions.new(**options.to_h) unless options.is_a? ::Gapic::CallOptions
|
135
|
+
deadline = calculate_deadline options
|
136
|
+
retried_exception = nil
|
137
|
+
next_timeout = get_timeout deadline
|
138
|
+
|
139
|
+
begin
|
140
|
+
base_make_http_request(verb,
|
141
|
+
uri: uri,
|
142
|
+
body: body,
|
143
|
+
params: params,
|
144
|
+
metadata: options.metadata,
|
145
|
+
timeout: next_timeout,
|
146
|
+
is_server_streaming: is_server_streaming,
|
147
|
+
&block)
|
148
|
+
rescue ::Faraday::Error => e
|
149
|
+
next_timeout = get_timeout deadline
|
150
|
+
|
151
|
+
if next_timeout&.positive? && options.retry_policy.call(e)
|
152
|
+
retried_exception = e
|
153
|
+
retry
|
154
|
+
end
|
155
|
+
|
156
|
+
unless next_timeout&.positive?
|
157
|
+
raise Gapic::GRPC::DeadlineExceededError.new e.message, root_cause: retried_exception
|
158
|
+
end
|
159
|
+
|
160
|
+
raise e
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
private
|
165
|
+
|
166
|
+
##
|
167
|
+
# @private
|
168
|
+
# Sends a http request via Faraday
|
169
|
+
# @param verb [Symbol] http verb
|
170
|
+
# @param uri [String] uri to send this request to
|
171
|
+
# @param body [String, nil] a body to send with the request, nil for requests without a body
|
172
|
+
# @param params [Hash] query string parameters for the request
|
173
|
+
# @param metadata [Hash] additional headers for the request
|
130
174
|
# @param is_server_streaming [Boolean] flag if method is streaming
|
131
175
|
# @yieldparam chunk [String] The chunk of data received during server streaming.
|
132
176
|
# @return [Faraday::Response]
|
133
|
-
def
|
177
|
+
def base_make_http_request verb, uri:, body:, params:, metadata:, timeout:, is_server_streaming: false
|
134
178
|
if @numeric_enums && (!params.key?("$alt") || params["$alt"] == "json")
|
135
179
|
params = params.merge({ "$alt" => "json;enum-encoding=int" })
|
136
180
|
end
|
137
|
-
|
181
|
+
|
138
182
|
@connection.send verb, uri do |req|
|
139
183
|
req.params = params if params.any?
|
140
184
|
req.body = body unless body.nil?
|
141
|
-
req.headers = req.headers.merge
|
142
|
-
req.options.timeout =
|
185
|
+
req.headers = req.headers.merge metadata
|
186
|
+
req.options.timeout = timeout if timeout&.positive?
|
143
187
|
if is_server_streaming
|
144
188
|
req.options.on_data = proc do |chunk, _overall_received_bytes|
|
145
189
|
yield chunk
|
@@ -147,6 +191,18 @@ module Gapic
|
|
147
191
|
end
|
148
192
|
end
|
149
193
|
end
|
194
|
+
|
195
|
+
def calculate_deadline options
|
196
|
+
return if options.timeout.nil?
|
197
|
+
return if options.timeout.negative?
|
198
|
+
|
199
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC) + options.timeout
|
200
|
+
end
|
201
|
+
|
202
|
+
def get_timeout deadline
|
203
|
+
return if deadline.nil?
|
204
|
+
deadline - Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
205
|
+
end
|
150
206
|
end
|
151
207
|
end
|
152
208
|
end
|
@@ -15,6 +15,7 @@
|
|
15
15
|
module Gapic
|
16
16
|
module Rest
|
17
17
|
class GrpcTranscoder
|
18
|
+
##
|
18
19
|
# @private
|
19
20
|
# A single binding for GRPC-REST transcoding of a request
|
20
21
|
# It includes a uri template with bound field parameters, a HTTP method type,
|
@@ -25,7 +26,8 @@ module Gapic
|
|
25
26
|
# @attribute [r] template
|
26
27
|
# @return [String] The URI template for the request.
|
27
28
|
# @attribute [r] field_bindings
|
28
|
-
# @return [Array<FieldBinding>]
|
29
|
+
# @return [Array<Gapic::Rest::GrpcTranscoder::HttpBinding::FieldBinding>]
|
30
|
+
# The field bindings for the URI template variables.
|
29
31
|
# @attribute [r] body
|
30
32
|
# @return [String] The body template for the request.
|
31
33
|
class HttpBinding
|
@@ -41,6 +43,57 @@ module Gapic
|
|
41
43
|
@body = body
|
42
44
|
end
|
43
45
|
|
46
|
+
##
|
47
|
+
# @private
|
48
|
+
# Creates a new HttpBinding.
|
49
|
+
#
|
50
|
+
# @param uri_method [Symbol] The rest verb for the binding.
|
51
|
+
# @param uri_template [String] The string with uri template for the binding.
|
52
|
+
# This string will be expanded with the parameters from variable bindings.
|
53
|
+
# @param matches [Array<Array>] Variable bindings in an array. Every element
|
54
|
+
# of the array is an [Array] triplet, where:
|
55
|
+
# - the first element is a [String] field path (e.g. `foo.bar`) in the request
|
56
|
+
# to bind to
|
57
|
+
# - the second element is a [Regexp] to match the field value
|
58
|
+
# - the third element is a [Boolean] whether the slashes in the field value
|
59
|
+
# should be preserved (as opposed to escaped) when expanding the uri template.
|
60
|
+
# @param body [String, Nil] The body template, e.g. `*` or a field path.
|
61
|
+
#
|
62
|
+
# @return [Gapic::Rest::GrpcTranscoder::HttpBinding] The new binding.
|
63
|
+
def self.create_with_validation uri_method:, uri_template:, matches: [], body: nil
|
64
|
+
template = uri_template
|
65
|
+
|
66
|
+
matches.each do |name, _regex, _preserve_slashes|
|
67
|
+
unless uri_template =~ /({#{Regexp.quote name}})/
|
68
|
+
err_msg = "Binding configuration is incorrect: missing parameter in the URI template.\n" \
|
69
|
+
"Parameter `#{name}` is specified for matching but there is no corresponding parameter " \
|
70
|
+
"`{#{name}}` in the URI template."
|
71
|
+
raise ::Gapic::Common::Error, err_msg
|
72
|
+
end
|
73
|
+
|
74
|
+
template = template.gsub "{#{name}}", ""
|
75
|
+
end
|
76
|
+
|
77
|
+
if template =~ /{([a-zA-Z_.]+)}/
|
78
|
+
err_name = Regexp.last_match[1]
|
79
|
+
err_msg = "Binding configuration is incorrect: missing match configuration.\n" \
|
80
|
+
"Parameter `{#{err_name}}` is specified in the URI template but there is no " \
|
81
|
+
"corresponding match configuration for `#{err_name}`."
|
82
|
+
raise ::Gapic::Common::Error, err_msg
|
83
|
+
end
|
84
|
+
|
85
|
+
if body&.include? "."
|
86
|
+
raise ::Gapic::Common::Error,
|
87
|
+
"Provided body template `#{body}` points to a field in a sub-message. This is not supported."
|
88
|
+
end
|
89
|
+
|
90
|
+
field_bindings = matches.map do |name, regex, preserve_slashes|
|
91
|
+
HttpBinding::FieldBinding.new name, regex, preserve_slashes
|
92
|
+
end
|
93
|
+
|
94
|
+
HttpBinding.new uri_method, uri_template, field_bindings, body
|
95
|
+
end
|
96
|
+
|
44
97
|
# A single binding for a field of a request message.
|
45
98
|
# @attribute [r] field_path
|
46
99
|
# @return [String] The path of the bound field, e.g. `foo.bar`.
|
@@ -44,36 +44,11 @@ module Gapic
|
|
44
44
|
#
|
45
45
|
# @return [Gapic::Rest::GrpcTranscoder] The updated transcoder.
|
46
46
|
def with_bindings uri_method:, uri_template:, matches: [], body: nil
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
"Parameter `#{name}` is specified for matching but there is no corresponding parameter " \
|
53
|
-
"`{#{name}}` in the URI template."
|
54
|
-
raise ::Gapic::Common::Error, err_msg
|
55
|
-
end
|
56
|
-
|
57
|
-
template = template.gsub "{#{name}}", ""
|
58
|
-
end
|
59
|
-
|
60
|
-
if template =~ /{([a-zA-Z_.]+)}/
|
61
|
-
err_name = Regexp.last_match[1]
|
62
|
-
err_msg = "Binding configuration is incorrect: missing match configuration.\n" \
|
63
|
-
"Parameter `{#{err_name}}` is specified in the URI template but there is no " \
|
64
|
-
"corresponding match configuration for `#{err_name}`."
|
65
|
-
raise ::Gapic::Common::Error, err_msg
|
66
|
-
end
|
67
|
-
|
68
|
-
if body&.include? "."
|
69
|
-
raise ::Gapic::Common::Error,
|
70
|
-
"Provided body template `#{body}` points to a field in a sub-message. This is not supported."
|
71
|
-
end
|
72
|
-
|
73
|
-
field_bindings = matches.map do |name, regex, preserve_slashes|
|
74
|
-
HttpBinding::FieldBinding.new name, regex, preserve_slashes
|
75
|
-
end
|
76
|
-
GrpcTranscoder.new @bindings + [HttpBinding.new(uri_method, uri_template, field_bindings, body)]
|
47
|
+
binding = HttpBinding.create_with_validation(uri_method: uri_method,
|
48
|
+
uri_template: uri_template,
|
49
|
+
matches: matches,
|
50
|
+
body: body)
|
51
|
+
GrpcTranscoder.new @bindings + [binding]
|
77
52
|
end
|
78
53
|
|
79
54
|
##
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gapic-common
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.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: 2022-11-
|
11
|
+
date: 2022-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -288,6 +288,7 @@ files:
|
|
288
288
|
- RELEASING.md
|
289
289
|
- lib/gapic-common.rb
|
290
290
|
- lib/gapic/call_options.rb
|
291
|
+
- lib/gapic/call_options/error_codes.rb
|
291
292
|
- lib/gapic/call_options/retry_policy.rb
|
292
293
|
- lib/gapic/common.rb
|
293
294
|
- lib/gapic/common/error.rb
|