gapic-common 0.14.0 → 0.15.1

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: ea69666c3f5162e9949825974c29af5ca636527a25e67d0ce034c2bb6c39b201
4
- data.tar.gz: 68df57288727233549f5ababcd296b545bd4a1e10bdc29caae1891019c3995ba
3
+ metadata.gz: dd16594f62fa1e7145513111074f9fb1ad6988ac38fcd0c7b7a63d119269e66d
4
+ data.tar.gz: 3c0921a7825bbab864a9a8fb370cd24def7493c2af050545e71d0dc22a4f980e
5
5
  SHA512:
6
- metadata.gz: 8c83345123a2739aa89f31aefb00288c8ae7e831af653a654872601a2e646ddd9b7d7356aa82e403b5c2571cae2bd437fbf4ff8c38e70822cfc18c89ea89f883
7
- data.tar.gz: a95b2ec76934bec8140e6c65b627644833143f313117cd86d867dcda0e3bfdf00407f86c8b33d0f52165de5549c3207119a8b5b506cba5b9da8c41a58846cf78
6
+ metadata.gz: b2b26d265c79563ff7bc28b74f3be6536df070d4bf7ed3e347d734ffadd867cb44f3dfac8f8a6b624f2786a0942643d92c5bdbc2610e3b0f1072f39b7337eef6
7
+ data.tar.gz: c02d9dfc4f98dc243d67a910e8a855a18333c3258f515e973962848c46812c9df52008fa942027592b451dce0e4b739fe7bf4553a81bf3bb649a71741c2da484
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Release History
2
2
 
3
+ ### 0.15.1 (2022-11-18)
4
+
5
+ #### Bug Fixes
6
+
7
+ * Fixed uninitialized constant when checking retry policy for a REST call ([#857](https://github.com/googleapis/gapic-generator-ruby/issues/857))
8
+
9
+ ### 0.15.0 (2022-11-17)
10
+
11
+ #### Features
12
+
13
+ * retry policy now works for REST calls
14
+
3
15
  ### 0.14.0 (2022-11-08)
4
16
 
5
17
  #### 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
+ (defined?(::GRPC) && 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.14.0".freeze
17
+ VERSION = "0.15.1".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
@@ -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
  ##
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.14.0
4
+ version: 0.15.1
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-08 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