gapic-common 0.14.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|