gapic-common 0.13.0 → 0.15.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b5964ec91020c76501e2424be598b345a114a16515fe209135e46f552100d4e
4
- data.tar.gz: 4a08e08fe15b6c6d6a3ad3097895a7d01bcfe3377f1392946a0cfe671ca97fdf
3
+ metadata.gz: 5902b53f0f5a46b4682ff855fb89a6a3162af38523fa273f273abeeeed0d3a3d
4
+ data.tar.gz: a1e9bb69d31725768f00b152efcaf29042657fbb304c2ba2f25de485831fe187
5
5
  SHA512:
6
- metadata.gz: a0270a8d4933fda1f6297233f3465ae4fed20d34ebbf4bb766f228fe13746b5508c97179eb7c0b763d104c52079f59765b514c32a1d6cb2d61196791f007595a
7
- data.tar.gz: 437633278a8640eee28a975c7821270b11c2127c72970e0259c29b5b643db37b8d394ac5ae1cd80cb367e10c1384311cc018e0a276804dfda7d8a91f9fffb13a
6
+ metadata.gz: 84d77cc3d943714b8a3578ecabf3fea3a321dfe0929ee108233d4dcd8fede90a37be21a81e121142739aa3dca102ffff0826a003906bec16f03749beddf59ab2
7
+ data.tar.gz: 27e2815be724399a4c01ca1d47c7b2e9291ee4583018251f45a2a0162f1d5cd8298d0ca3b8a4cf90fc4ba6f2e410240439e61a22a66fbeae89c5a3e9dc223879
data/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # Release History
2
2
 
3
+ ### 0.15.0 (2022-11-17)
4
+
5
+ #### Features
6
+
7
+ * retry policy now works for REST calls
8
+
9
+ ### 0.14.0 (2022-11-08)
10
+
11
+ #### Features
12
+
13
+ * add support for different types of credentials to REST
14
+ #### Bug Fixes
15
+
16
+ * deadlock fix ([#845](https://github.com/googleapis/gapic-generator-ruby/issues/845))
17
+
3
18
  ### 0.13.0 (2022-10-26)
4
19
 
5
20
  #### Features
@@ -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
@@ -12,6 +12,7 @@
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"
15
16
  require "gapic/call_options/retry_policy"
16
17
 
17
18
  module Gapic
@@ -14,6 +14,6 @@
14
14
 
15
15
  module Gapic
16
16
  module Common
17
- VERSION = "0.13.0".freeze
17
+ VERSION = "0.15.0".freeze
18
18
  end
19
19
  end
@@ -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
- # to the REST call. Currently only timeout and headers are supported.
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 make_http_request verb, uri:, body:, params:, options:, is_server_streaming: false
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
- options = ::Gapic::CallOptions.new(**options.to_h) unless options.is_a? ::Gapic::CallOptions
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 options.metadata
142
- req.options.timeout = options.timeout if options.timeout&.positive?
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
@@ -18,22 +18,43 @@ module Gapic
18
18
  # Registers the middleware with Faraday
19
19
  module FaradayMiddleware
20
20
  ##
21
+ # @private
21
22
  # Request middleware that constructs the Authorization HTTP header
22
23
  # using ::Google::Auth::Credentials
23
24
  #
24
25
  class GoogleAuthorization < Faraday::Middleware
25
26
  ##
27
+ # @private
26
28
  # @param app [#call]
27
- # @param credentials [::Google::Auth::Credentials]
29
+ # @param credentials [Google::Auth::Credentials, Signet::OAuth2::Client, Symbol, Proc]
30
+ # Provides the means for authenticating requests made by
31
+ # the client. This parameter can be many types:
32
+ # * A `Google::Auth::Credentials` uses a the properties of its represented keyfile for authenticating requests
33
+ # made by this client.
34
+ # * A `Signet::OAuth2::Client` object used to apply the OAuth credentials.
35
+ # * A `Proc` will be used as an updater_proc for the auth token.
36
+ # * A `Symbol` is treated as a signal that authentication is not required.
37
+ #
28
38
  def initialize app, credentials
29
- @credentials = credentials
39
+ @updater_proc = case credentials
40
+ when Symbol
41
+ credentials
42
+ else
43
+ updater_proc = credentials.updater_proc if credentials.respond_to? :updater_proc
44
+ updater_proc ||= credentials if credentials.is_a? Proc
45
+ raise ArgumentError, "invalid credentials (#{credentials.class})" if updater_proc.nil?
46
+ updater_proc
47
+ end
30
48
  super app
31
49
  end
32
50
 
51
+ # @private
33
52
  # @param env [Faraday::Env]
34
53
  def call env
35
- auth_hash = @credentials.client.apply({})
36
- env.request_headers["Authorization"] = auth_hash[:authorization]
54
+ unless @updater_proc.is_a? Symbol
55
+ auth_hash = @updater_proc.call({})
56
+ env.request_headers["Authorization"] = auth_hash[:authorization]
57
+ end
37
58
 
38
59
  @app.call env
39
60
  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>] The field bindings for the URI template variables.
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
- template = uri_template
48
-
49
- matches.each do |name, _regex, _preserve_slashes|
50
- unless uri_template =~ /({#{Regexp.quote name}})/
51
- err_msg = "Binding configuration is incorrect: missing parameter in the URI template.\n" \
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
  ##
@@ -44,6 +44,7 @@ module Gapic
44
44
 
45
45
  Thread.new do
46
46
  yield @in_q, @out_q
47
+ @out_q.enq nil
47
48
  rescue StandardError => e
48
49
  @out_q.push e
49
50
  end
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.13.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-10-26 00:00:00.000000000 Z
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