gapic-generator 0.52.0 → 0.53.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 +5 -0
- data/lib/gapic/generator/version.rb +1 -1
- data/lib/gapic/generators/default_generator.rb +6 -0
- data/lib/gapic/model/method/resumable_upload.rb +143 -0
- data/lib/gapic/presenters/gem_presenter.rb +1 -1
- data/lib/gapic/presenters/method_presenter.rb +35 -0
- data/lib/gapic/presenters/service_presenter.rb +65 -0
- data/lib/gapic/presenters/service_rest_presenter.rb +12 -0
- data/lib/gapic/presenters/snippet/response_handling_presenters.rb +60 -0
- data/lib/gapic/presenters/snippet_presenter.rb +16 -6
- data/templates/default/lib/_service.text.erb +3 -0
- data/templates/default/lib/rest/_rest.text.erb +3 -0
- data/templates/default/service/client/_client.text.erb +18 -0
- data/templates/default/service/client/_config.text.erb +8 -0
- data/templates/default/service/client/method/_def.text.erb +5 -1
- data/templates/default/service/client/method/def/_options_defaults.text.erb +5 -0
- data/templates/default/service/client/method/def/_response.text.erb +3 -1
- data/templates/default/service/client/method/def/_response_resumable_upload.text.erb +13 -0
- data/templates/default/service/client/method/def/_upload_error_handler.text.erb +2 -0
- data/templates/default/service/client/method/docs/_request_normal.text.erb +19 -0
- data/templates/default/service/client/method/docs/_response.text.erb +8 -0
- data/templates/default/service/rest/client/_client.text.erb +18 -0
- data/templates/default/service/rest/client/_config.text.erb +8 -0
- data/templates/default/service/rest/client/method/_def.text.erb +5 -1
- data/templates/default/service/rest/client/method/def/_response.text.erb +3 -1
- data/templates/default/service/rest/client/method/def/_response_resumable_upload.text.erb +13 -0
- data/templates/default/service/rest/client/method/def/_upload_error_handler.text.erb +2 -0
- data/templates/default/service/rest/client/method/docs/_request.text.erb +19 -0
- data/templates/default/service/rest/client/method/docs/_result.text.erb +7 -1
- data/templates/default/service/rest/service_stub/_service_stub.text.erb +2 -2
- data/templates/default/service/rest/service_stub/grpc_transcoding_method/_bindings.text.erb +15 -0
- data/templates/default/service/rest/service_stub/grpc_transcoding_method/_def.text.erb +1 -14
- data/templates/default/service/rest/test/client.text.erb +1 -1
- data/templates/default/service/resumable_upload_stub/_resumable_upload_stub.text.erb +64 -0
- data/templates/default/service/resumable_upload_stub/_transcoding_method.text.erb +22 -0
- data/templates/default/service/resumable_upload_stub.text.erb +6 -0
- data/templates/default/service/test/client.text.erb +1 -1
- data/templates/default/service/test/resumable_upload.text.erb +132 -0
- metadata +11 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3264cfe286069bf2e3bed64ae2246c0b8e48d97851809c99c5520e072fa38889
|
|
4
|
+
data.tar.gz: d9503be57f76aedd856a46159e138673fc83f2912fa51018d16e5cd1e8c71f90
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: d8109c1036d6b95c2bf2fe201de7e2cf26516e4d315c6d4ca3331b52f0d312d27884416bd6ce7db8209ae78c13ffab4120b444e229fc914d3d329ca801dd6837
|
|
7
|
+
data.tar.gz: 1ef6ae68e1fc76dfc19bbe947d7f4340918403494d57bd3d1ba40540b953921470a5090b7ed7f6d2fe80519066c28d92e8a0a3115acbf4d498fc43c8580debd9
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
# Release History for gapic-generator
|
|
2
2
|
|
|
3
|
+
### 0.53.0 / 2026-09-30
|
|
4
|
+
|
|
5
|
+
* Feature: update gapic-common for generated libraries to 1.4
|
|
6
|
+
* Feature: resumable upload support in gapic-generator
|
|
7
|
+
|
|
3
8
|
### 0.52.0 / 2026-09-04
|
|
4
9
|
|
|
5
10
|
* Fix: escape multi-line braces and backtick unknown doc tags in yard formatting
|
|
@@ -92,10 +92,16 @@ module Gapic
|
|
|
92
92
|
# Rest-only `service.stub` file
|
|
93
93
|
files << g("service/rest/service_stub", "lib/#{service.rest.service_stub_file_path}", service: service) if should_generate_rest
|
|
94
94
|
|
|
95
|
+
# Resumable upload stub, shared by both transports because uploads always travel over REST
|
|
96
|
+
files << g("service/resumable_upload_stub", "lib/#{service.resumable_upload_stub_file_path}", service: service) if service.resumable_upload?
|
|
97
|
+
|
|
95
98
|
# Unit tests for `client.rb`
|
|
96
99
|
files << g("service/test/client", "test/#{service.test_client_file_path}", service: service) if should_generate_grpc
|
|
97
100
|
files << g("service/rest/test/client", "test/#{service.rest.test_client_file_path}", service: service) if should_generate_rest
|
|
98
101
|
|
|
102
|
+
# Unit tests for resumable upload RPCs, which the client tests above skip
|
|
103
|
+
files << g("service/test/resumable_upload", "test/#{service.test_resumable_upload_file_path}", service: service) if service.resumable_upload?
|
|
104
|
+
|
|
99
105
|
# Unit tests for `paths.rb`
|
|
100
106
|
files << g("service/test/client_paths", "test/#{service.test_paths_file_path}", service: service) if service.paths? && should_generate_grpc
|
|
101
107
|
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright 2026 Google LLC
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
# you may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# https://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
require "gapic/model/model_error"
|
|
18
|
+
|
|
19
|
+
module Gapic
|
|
20
|
+
module Model
|
|
21
|
+
module Method
|
|
22
|
+
##
|
|
23
|
+
# Resumable upload method-level model.
|
|
24
|
+
#
|
|
25
|
+
# A resumable upload RPC does not send its payload in the initiation request. The request it
|
|
26
|
+
# describes only creates an upload session; the bytes travel afterwards, over REST, in chunks
|
|
27
|
+
# addressed to a URL the server hands back. Generated clients therefore return an upload handle
|
|
28
|
+
# from such a method rather than a response message.
|
|
29
|
+
#
|
|
30
|
+
# Until the upload annotation is published, the set of such RPCs is carried here as a table, and
|
|
31
|
+
# so is the URL prefix each one's initiation request is sent under. When the annotation lands,
|
|
32
|
+
# {.url_prefix_for} keeps the table and detection moves to `http.media_upload.enabled`.
|
|
33
|
+
#
|
|
34
|
+
# @!attribute [r] url_prefix
|
|
35
|
+
# @return [String] The path prefix prepended to the transcoded initiation URL, without
|
|
36
|
+
# surrounding slashes, e.g. `resumable/upload`.
|
|
37
|
+
#
|
|
38
|
+
class ResumableUpload
|
|
39
|
+
# @return [String]
|
|
40
|
+
attr_reader :url_prefix
|
|
41
|
+
|
|
42
|
+
##
|
|
43
|
+
# @param url_prefix [String] The upload URL prefix for the matched RPC.
|
|
44
|
+
#
|
|
45
|
+
def initialize url_prefix
|
|
46
|
+
@url_prefix = url_prefix
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
##
|
|
50
|
+
# Exact matches, keyed by the full gRPC name of the RPC.
|
|
51
|
+
#
|
|
52
|
+
EXACT_PREFIXES = {
|
|
53
|
+
"google.showcase.v1beta1.ResumableUploadService.UploadMedia" => "resumable/upload"
|
|
54
|
+
}.freeze
|
|
55
|
+
|
|
56
|
+
##
|
|
57
|
+
# Version-family matches, for protos that are republished under a new version regularly.
|
|
58
|
+
# Anchored on the left at the package and on the right at the service and method, with the
|
|
59
|
+
# intervening segments (e.g. `.services.`) unconstrained.
|
|
60
|
+
#
|
|
61
|
+
VERSIONED_PREFIXES = [
|
|
62
|
+
{
|
|
63
|
+
left: /\Agoogle\.ads\.googleads\.v[0-9_]+\./,
|
|
64
|
+
right: ".YouTubeVideoUploadService.CreateYouTubeVideoUpload",
|
|
65
|
+
prefix: "resumable/upload"
|
|
66
|
+
}
|
|
67
|
+
].freeze
|
|
68
|
+
|
|
69
|
+
class << self
|
|
70
|
+
##
|
|
71
|
+
# Inspects a method and returns its resumable upload model, or `nil` if it does not perform
|
|
72
|
+
# resumable uploads.
|
|
73
|
+
#
|
|
74
|
+
# @param method [Gapic::Presenters::MethodPresenter]
|
|
75
|
+
#
|
|
76
|
+
# @raise [Gapic::Model::ModelError] if the method is a resumable upload RPC that the
|
|
77
|
+
# generator cannot generate an upload surface for.
|
|
78
|
+
#
|
|
79
|
+
# @return [Gapic::Model::Method::ResumableUpload, nil]
|
|
80
|
+
#
|
|
81
|
+
def create method
|
|
82
|
+
prefix = url_prefix_for method.grpc_full_name
|
|
83
|
+
return nil if prefix.nil?
|
|
84
|
+
validate! method
|
|
85
|
+
new prefix
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
##
|
|
89
|
+
# The upload URL prefix for an RPC, or `nil` if the RPC does not perform resumable uploads.
|
|
90
|
+
#
|
|
91
|
+
# @param full_name [String] The full gRPC name of the RPC,
|
|
92
|
+
# e.g. `google.showcase.v1beta1.ResumableUploadService.UploadMedia`.
|
|
93
|
+
#
|
|
94
|
+
# @return [String, nil]
|
|
95
|
+
#
|
|
96
|
+
def url_prefix_for full_name
|
|
97
|
+
EXACT_PREFIXES[full_name] ||
|
|
98
|
+
VERSIONED_PREFIXES.find do |match|
|
|
99
|
+
match[:left].match?(full_name) && full_name.end_with?(match[:right])
|
|
100
|
+
end&.fetch(:prefix)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
##
|
|
104
|
+
# Verifies that an upload surface can be generated for the given method. A resumable upload
|
|
105
|
+
# is a single unary POST that carries a body, and anything else in the table is a
|
|
106
|
+
# misconfiguration that must fail the build rather than generate code that cannot work.
|
|
107
|
+
#
|
|
108
|
+
# @param method [Gapic::Presenters::MethodPresenter]
|
|
109
|
+
#
|
|
110
|
+
# @raise [Gapic::Model::ModelError]
|
|
111
|
+
#
|
|
112
|
+
# @return [void]
|
|
113
|
+
#
|
|
114
|
+
def validate! method
|
|
115
|
+
reason = unsupported_reason method
|
|
116
|
+
return if reason.nil?
|
|
117
|
+
raise ModelError, "The method #{method.grpc_full_name} performs resumable uploads, " \
|
|
118
|
+
"which the generator supports only for #{reason}."
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
private
|
|
122
|
+
|
|
123
|
+
##
|
|
124
|
+
# @param method [Gapic::Presenters::MethodPresenter]
|
|
125
|
+
# @return [String, nil] What the method would have had to be, or `nil` if it is supported.
|
|
126
|
+
#
|
|
127
|
+
def unsupported_reason method
|
|
128
|
+
return "non-streaming methods" if method.client_streaming? || method.server_streaming?
|
|
129
|
+
return "non-paginated methods" if method.paged?
|
|
130
|
+
return "methods that are not long-running operations" if method.lro? || method.nonstandard_lro?
|
|
131
|
+
|
|
132
|
+
binding = method.http_bindings.first
|
|
133
|
+
return "methods with an HTTP binding" if binding.nil?
|
|
134
|
+
return "methods bound to POST" unless binding.verb == :post
|
|
135
|
+
return "methods whose HTTP binding has a body" unless binding.body?
|
|
136
|
+
|
|
137
|
+
nil
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -260,7 +260,7 @@ module Gapic
|
|
|
260
260
|
|
|
261
261
|
def dependencies
|
|
262
262
|
@dependencies ||= begin
|
|
263
|
-
deps = { "gapic-common" => "~> 1.
|
|
263
|
+
deps = { "gapic-common" => "~> 1.5" }
|
|
264
264
|
deps["grpc-google-iam-v1"] = "~> 1.11" if iam_dependency?
|
|
265
265
|
extra_deps = gem_config_dependencies
|
|
266
266
|
deps.merge! mixins_model.dependencies if mixins_model.mixins?
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
require "active_support/inflector"
|
|
18
18
|
require "gapic/ruby_info"
|
|
19
19
|
require "gapic/helpers/namespace_helper"
|
|
20
|
+
require "gapic/model/method/resumable_upload"
|
|
20
21
|
|
|
21
22
|
module Gapic
|
|
22
23
|
module Presenters
|
|
@@ -71,6 +72,10 @@ module Gapic
|
|
|
71
72
|
@lro = Gapic::Model::Method.parse_lro @method, @api
|
|
72
73
|
|
|
73
74
|
@rest = MethodRestPresenter.new self, @api
|
|
75
|
+
|
|
76
|
+
# Built last: detection is cheap but its validation reads the LRO model, the HTTP bindings
|
|
77
|
+
# and the pagination check, all of which have to exist first.
|
|
78
|
+
@resumable_upload = Gapic::Model::Method::ResumableUpload.create self
|
|
74
79
|
end
|
|
75
80
|
|
|
76
81
|
##
|
|
@@ -279,6 +284,36 @@ module Gapic
|
|
|
279
284
|
service.nonstandard_lros.find { |model| model.service == @lro.service_full_name }
|
|
280
285
|
end
|
|
281
286
|
|
|
287
|
+
##
|
|
288
|
+
# Whether this method performs a resumable upload. Such a method returns an upload handle
|
|
289
|
+
# rather than a response, and its payload travels over REST in chunks after the request this
|
|
290
|
+
# method describes has created the upload session.
|
|
291
|
+
#
|
|
292
|
+
# @return [Boolean]
|
|
293
|
+
#
|
|
294
|
+
def resumable_upload?
|
|
295
|
+
!@resumable_upload.nil?
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
##
|
|
299
|
+
# The path prefix prepended to this method's transcoded initiation URL, without surrounding
|
|
300
|
+
# slashes, e.g. `resumable/upload`. `nil` unless this method performs a resumable upload.
|
|
301
|
+
#
|
|
302
|
+
# @return [String, nil]
|
|
303
|
+
#
|
|
304
|
+
def upload_url_prefix
|
|
305
|
+
@resumable_upload&.url_prefix
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
##
|
|
309
|
+
# The name of the constant the generated upload stub holds this method's URL prefix in.
|
|
310
|
+
#
|
|
311
|
+
# @return [String]
|
|
312
|
+
#
|
|
313
|
+
def upload_url_prefix_const_name
|
|
314
|
+
"#{name.upcase}_URL_PREFIX"
|
|
315
|
+
end
|
|
316
|
+
|
|
282
317
|
def client_streaming?
|
|
283
318
|
@method.client_streaming
|
|
284
319
|
end
|
|
@@ -422,6 +422,15 @@ module Gapic
|
|
|
422
422
|
service_file_path.sub ".rb", "_operations_test.rb"
|
|
423
423
|
end
|
|
424
424
|
|
|
425
|
+
##
|
|
426
|
+
# Path of the generated tests covering this service's resumable upload RPCs. Those RPCs are
|
|
427
|
+
# excluded from the ordinary client tests, which assume a call returns a response.
|
|
428
|
+
#
|
|
429
|
+
# @return [String]
|
|
430
|
+
def test_resumable_upload_file_path
|
|
431
|
+
service_file_path.sub ".rb", "_resumable_upload_test.rb"
|
|
432
|
+
end
|
|
433
|
+
|
|
425
434
|
def stub_name
|
|
426
435
|
"#{ActiveSupport::Inflector.underscore name}_stub"
|
|
427
436
|
end
|
|
@@ -489,6 +498,62 @@ module Gapic
|
|
|
489
498
|
ServicePresenter.new @gem_presenter, @api, lro.services.first, parent_service: self unless lro.nil?
|
|
490
499
|
end
|
|
491
500
|
|
|
501
|
+
##
|
|
502
|
+
# Whether any of this service's RPCs perform resumable uploads, and therefore whether an upload
|
|
503
|
+
# stub has to be generated for it and built by its clients.
|
|
504
|
+
#
|
|
505
|
+
# @return [Boolean]
|
|
506
|
+
def resumable_upload?
|
|
507
|
+
methods.any?(&:resumable_upload?)
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
##
|
|
511
|
+
# Presenters for the RPCs of this service that perform resumable uploads.
|
|
512
|
+
#
|
|
513
|
+
# @return [Enumerable<Gapic::Presenters::MethodPresenter>]
|
|
514
|
+
def resumable_upload_methods
|
|
515
|
+
methods.select(&:resumable_upload?)
|
|
516
|
+
end
|
|
517
|
+
|
|
518
|
+
##
|
|
519
|
+
# The class name of the generated upload stub. One per service, shared by both transports, and
|
|
520
|
+
# deliberately not nested under `Rest::`: the gRPC client builds it too, because the upload
|
|
521
|
+
# itself always travels over REST.
|
|
522
|
+
#
|
|
523
|
+
# @return [String]
|
|
524
|
+
def resumable_upload_stub_name
|
|
525
|
+
"ResumableUploadStub"
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
# @return [String]
|
|
529
|
+
def resumable_upload_stub_name_full
|
|
530
|
+
fix_namespace @api, "#{service_name_full}::#{resumable_upload_stub_name}"
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
# @return [String]
|
|
534
|
+
def resumable_upload_stub_require
|
|
535
|
+
ruby_file_path @api, resumable_upload_stub_name_full
|
|
536
|
+
end
|
|
537
|
+
|
|
538
|
+
# @return [String]
|
|
539
|
+
def resumable_upload_stub_file_path
|
|
540
|
+
"#{resumable_upload_stub_require}.rb"
|
|
541
|
+
end
|
|
542
|
+
|
|
543
|
+
# @return [String]
|
|
544
|
+
def resumable_upload_stub_file_name
|
|
545
|
+
resumable_upload_stub_file_path.split("/").last
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
##
|
|
549
|
+
# An instance variable name used for the generated upload stub. The clients keep the stub here
|
|
550
|
+
# and expose no reader for it.
|
|
551
|
+
#
|
|
552
|
+
# @return [String]
|
|
553
|
+
def resumable_upload_stub_ivar
|
|
554
|
+
"@resumable_upload_stub"
|
|
555
|
+
end
|
|
556
|
+
|
|
492
557
|
def config_channel_args
|
|
493
558
|
{ "grpc.service_config_disable_resolution" => 1 }
|
|
494
559
|
end
|
|
@@ -357,6 +357,18 @@ module Gapic
|
|
|
357
357
|
main_service.methods.select(&:can_generate_rest?)
|
|
358
358
|
end
|
|
359
359
|
|
|
360
|
+
##
|
|
361
|
+
# Presenters for methods that the REST service stub carries an implementation for. An upload
|
|
362
|
+
# RPC has no ordinary REST path: the REST client delegates to the upload handle exactly as the
|
|
363
|
+
# gRPC client does, so a plain call method and transcoder here would be dead code that also
|
|
364
|
+
# happens to be wrong — a non-resumable POST of the whole payload.
|
|
365
|
+
#
|
|
366
|
+
# @return [Enumerable<Gapic::Presenters::MethodPresenter>]
|
|
367
|
+
#
|
|
368
|
+
def service_stub_methods
|
|
369
|
+
methods.reject(&:resumable_upload?)
|
|
370
|
+
end
|
|
371
|
+
|
|
360
372
|
##
|
|
361
373
|
# Require string for the helpers file
|
|
362
374
|
#
|
|
@@ -80,6 +80,66 @@ module Gapic
|
|
|
80
80
|
attr_reader :response_name
|
|
81
81
|
end
|
|
82
82
|
|
|
83
|
+
##
|
|
84
|
+
# Presentation information about resumable upload response handling.
|
|
85
|
+
#
|
|
86
|
+
# A resumable upload RPC returns a {::Gapic::ResumableUpload} handle rather than a
|
|
87
|
+
# response message, so the snippet names the call result `upload` and goes on to
|
|
88
|
+
# start the upload, which is what actually produces the response message.
|
|
89
|
+
#
|
|
90
|
+
class ResumableUploadResponseHandlingPresenter
|
|
91
|
+
include ResponseHandlingPresenterCommon
|
|
92
|
+
|
|
93
|
+
##
|
|
94
|
+
# Create a resumable upload response handling presenter
|
|
95
|
+
#
|
|
96
|
+
# @param proto [Google::Cloud::Tools::SnippetGen::ConfigLanguage::V1::Snippet::SimpleResponseHandling]
|
|
97
|
+
# The protobuf representation
|
|
98
|
+
# @param json [String]
|
|
99
|
+
# The JSON representation
|
|
100
|
+
# @param response_type [String] The fully qualified response message class
|
|
101
|
+
# @param phase1 [Boolean] True if this is a phase 1 snippet without config
|
|
102
|
+
#
|
|
103
|
+
def initialize proto, _json, response_type:, phase1:
|
|
104
|
+
@response_name = phase1 ? "upload" : compute_response_name(proto, phase1)
|
|
105
|
+
@render_lines = phase1 ? upload_lines(response_type) : []
|
|
106
|
+
@render = @render_lines.join "\n"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
##
|
|
110
|
+
# The lines of rendered code
|
|
111
|
+
# @return [Array<String>]
|
|
112
|
+
#
|
|
113
|
+
attr_reader :render_lines
|
|
114
|
+
|
|
115
|
+
##
|
|
116
|
+
# The rendered code as a single string, possibly with line breaks
|
|
117
|
+
# @return [String]
|
|
118
|
+
#
|
|
119
|
+
attr_reader :render
|
|
120
|
+
|
|
121
|
+
##
|
|
122
|
+
# The name of the response variable, or nil for no response handling
|
|
123
|
+
# @return [String,nil]
|
|
124
|
+
#
|
|
125
|
+
attr_reader :response_name
|
|
126
|
+
|
|
127
|
+
private
|
|
128
|
+
|
|
129
|
+
def upload_lines response_type
|
|
130
|
+
[
|
|
131
|
+
"# The returned object is a handle for a resumable upload. Nothing has been",
|
|
132
|
+
"# uploaded yet, and the timeout and retry policy of the call above cover only",
|
|
133
|
+
"# the request that creates the upload session, not the upload as a whole.",
|
|
134
|
+
"stream = File.open \"input.bin\", \"rb\"",
|
|
135
|
+
"result = #{@response_name}.start stream: stream, content_type: \"application/octet-stream\"",
|
|
136
|
+
"",
|
|
137
|
+
"# The returned object is of type #{response_type}.",
|
|
138
|
+
"p result"
|
|
139
|
+
]
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
83
143
|
##
|
|
84
144
|
# Presentation information about LRO response handling
|
|
85
145
|
#
|
|
@@ -63,6 +63,8 @@ module Gapic
|
|
|
63
63
|
:paged
|
|
64
64
|
elsif @method_presenter.lro?
|
|
65
65
|
:lro
|
|
66
|
+
elsif @method_presenter.resumable_upload?
|
|
67
|
+
:resumable_upload
|
|
66
68
|
else
|
|
67
69
|
:simple
|
|
68
70
|
end
|
|
@@ -244,13 +246,12 @@ module Gapic
|
|
|
244
246
|
LroResponseHandlingPresenter.new call_proto&.lro_handling,
|
|
245
247
|
call_json&.fetch("lroHandling", nil),
|
|
246
248
|
phase1: phase1
|
|
249
|
+
when :resumable_upload
|
|
250
|
+
ResumableUploadResponseHandlingPresenter.new call_proto&.response_handling,
|
|
251
|
+
call_json&.fetch("responseHandling", nil),
|
|
252
|
+
response_type: return_type, phase1: phase1
|
|
247
253
|
when :streaming
|
|
248
|
-
|
|
249
|
-
response_name = nil if response_name == ""
|
|
250
|
-
StreamingResponseHandlingPresenter.new call_proto&.response_handling,
|
|
251
|
-
call_json&.fetch("responseHandling", nil),
|
|
252
|
-
response_name: response_name, base_response_type: base_response_type,
|
|
253
|
-
phase1: phase1
|
|
254
|
+
build_streaming_response_handling_presenter call_proto, call_json, phase1
|
|
254
255
|
else
|
|
255
256
|
SimpleResponseHandlingPresenter.new call_proto&.response_handling,
|
|
256
257
|
call_json&.fetch("responseHandling", nil),
|
|
@@ -258,6 +259,15 @@ module Gapic
|
|
|
258
259
|
end
|
|
259
260
|
end
|
|
260
261
|
|
|
262
|
+
def build_streaming_response_handling_presenter call_proto, call_json, phase1
|
|
263
|
+
response_name = phase1 ? "output" : call_proto&.server_stream_name
|
|
264
|
+
response_name = nil if response_name == ""
|
|
265
|
+
StreamingResponseHandlingPresenter.new call_proto&.response_handling,
|
|
266
|
+
call_json&.fetch("responseHandling", nil),
|
|
267
|
+
response_name: response_name, base_response_type: base_response_type,
|
|
268
|
+
phase1: phase1
|
|
269
|
+
end
|
|
270
|
+
|
|
261
271
|
def build_client_call_presenter call_proto, call_json, request_name, response_name
|
|
262
272
|
phase1 = !config?
|
|
263
273
|
if response_kind == :paged
|
|
@@ -15,6 +15,9 @@ require "<%= service.credentials_require %>"
|
|
|
15
15
|
<%- if service.paths? -%>
|
|
16
16
|
require "<%= service.paths_require %>"
|
|
17
17
|
<%- end -%>
|
|
18
|
+
<%- if service.resumable_upload? -%>
|
|
19
|
+
require "<%= service.resumable_upload_stub_require %>"
|
|
20
|
+
<%- end -%>
|
|
18
21
|
<%- if service.generate_grpc_clients? -%>
|
|
19
22
|
<%- if service.lro? -%>
|
|
20
23
|
require "<%= service.operations_require %>"
|
|
@@ -15,6 +15,9 @@ require "<%= service.credentials_require %>"
|
|
|
15
15
|
<%- if service.paths? -%>
|
|
16
16
|
require "<%= service.paths_require %>"
|
|
17
17
|
<%- end -%>
|
|
18
|
+
<%- if service.resumable_upload? -%>
|
|
19
|
+
require "<%= service.resumable_upload_stub_require %>"
|
|
20
|
+
<%- end -%>
|
|
18
21
|
<%- if service.rest.lro? -%>
|
|
19
22
|
require "<%= service.rest.operations_require %>"
|
|
20
23
|
<%- end -%>
|
|
@@ -20,6 +20,14 @@ require "securerandom"
|
|
|
20
20
|
<%= indent service.doc_description(transport: :grpc), "# " %>
|
|
21
21
|
#
|
|
22
22
|
<%- end -%>
|
|
23
|
+
<%- if service.resumable_upload? -%>
|
|
24
|
+
<%- upload_names = service.resumable_upload_methods.map { |upload_method| "`#{upload_method.name}`" }.join ", " -%>
|
|
25
|
+
<%- upload_many = service.resumable_upload_methods.length > 1 -%>
|
|
26
|
+
# <%= upload_names %> <%= upload_many ? "perform resumable uploads: each returns" : "performs a resumable upload: it returns" %> a {::Gapic::ResumableUpload} handle
|
|
27
|
+
# instead of a response, and the per-call `timeout` and retry policy cover only the request that
|
|
28
|
+
# creates the upload session, not the upload itself.
|
|
29
|
+
#
|
|
30
|
+
<%- end -%>
|
|
23
31
|
class <%= service.client_name %>
|
|
24
32
|
# @private
|
|
25
33
|
API_VERSION = "<%= service.api_version %>".freeze
|
|
@@ -140,6 +148,16 @@ class <%= service.client_name %>
|
|
|
140
148
|
config.universe_domain = @config.universe_domain
|
|
141
149
|
end
|
|
142
150
|
|
|
151
|
+
<%- end -%>
|
|
152
|
+
<%- if service.resumable_upload? -%>
|
|
153
|
+
<%= service.resumable_upload_stub_ivar %> = <%= service.resumable_upload_stub_name_full %>.new(
|
|
154
|
+
endpoint: @config.endpoint,
|
|
155
|
+
endpoint_template: DEFAULT_ENDPOINT_TEMPLATE,
|
|
156
|
+
universe_domain: @config.universe_domain,
|
|
157
|
+
credentials: credentials,
|
|
158
|
+
logger: @config.logger
|
|
159
|
+
)
|
|
160
|
+
|
|
143
161
|
<%- end -%>
|
|
144
162
|
@<%= service.stub_name %> = ::Gapic::ServiceStub.new(
|
|
145
163
|
<%= service.proto_service_stub_name_full %>,
|
|
@@ -190,6 +190,14 @@ class Configuration
|
|
|
190
190
|
<%- method_service.methods.each do |method| -%>
|
|
191
191
|
##
|
|
192
192
|
# RPC-specific configuration for `<%= method.name %>`
|
|
193
|
+
<%- if method.resumable_upload? -%>
|
|
194
|
+
#
|
|
195
|
+
# `<%= method.name %>` performs a resumable upload, so the `timeout` and `retry_policy`
|
|
196
|
+
# configured here cover the request that creates the upload session only, not the upload
|
|
197
|
+
# itself. The whole-upload budget is the `upload_timeout:` argument of
|
|
198
|
+
# {::Gapic::ResumableUpload#start} and {::Gapic::ResumableUpload#resume}.
|
|
199
|
+
#
|
|
200
|
+
<%- end -%>
|
|
193
201
|
# @return [::Gapic::Config::Method]
|
|
194
202
|
#
|
|
195
203
|
attr_reader :<%= method.name %>
|
|
@@ -9,15 +9,19 @@
|
|
|
9
9
|
#
|
|
10
10
|
<%= render partial: "service/client/method/docs/response", locals: { method: method } -%>
|
|
11
11
|
#
|
|
12
|
+
<%- unless method.resumable_upload? -%>
|
|
12
13
|
<%= render partial: "service/client/method/docs/error", locals: { method: method } -%>
|
|
13
14
|
#
|
|
15
|
+
<%- end -%>
|
|
14
16
|
<%= render partial: "service/client/method/docs/snippets", locals: { method: method } -%>
|
|
15
17
|
<%= render partial: "service/client/method/docs/samples", locals: { method: method } -%>
|
|
16
|
-
def <%= method.name %> request
|
|
18
|
+
def <%= method.name %> request<%= method.resumable_upload? ? " = {}" : "" %>, options = nil
|
|
17
19
|
<%= indent render(partial: "service/client/method/def/request", locals: { method: method }), 2 %>
|
|
18
20
|
|
|
19
21
|
<%= indent render(partial: "service/client/method/def/options_defaults", locals: { method: method }), 2 %>
|
|
20
22
|
|
|
21
23
|
<%= indent render(partial: "service/client/method/def/response", locals: { method: method }), 2 %>
|
|
24
|
+
<%- unless method.resumable_upload? -%>
|
|
22
25
|
<%= render partial: "service/client/method/def/rescue", locals: { method: method } -%>
|
|
26
|
+
<%- end -%>
|
|
23
27
|
end
|
|
@@ -8,7 +8,12 @@ metadata = @config.rpcs.<%= method.name %>.metadata.to_h
|
|
|
8
8
|
# Set x-goog-api-client, x-goog-user-project and x-goog-api-version headers
|
|
9
9
|
metadata[:"x-goog-api-client"] ||= ::Gapic::Headers.x_goog_api_client \
|
|
10
10
|
lib_name: @config.lib_name, lib_version: @config.lib_version,
|
|
11
|
+
<%- if method.resumable_upload? -%>
|
|
12
|
+
gapic_version: ::<%= method.service.gem.version_name_full %>,
|
|
13
|
+
transports_version_send: [:rest]
|
|
14
|
+
<%- else -%>
|
|
11
15
|
gapic_version: ::<%= method.service.gem.version_name_full %>
|
|
16
|
+
<%- end -%>
|
|
12
17
|
metadata[:"x-goog-api-version"] = API_VERSION unless API_VERSION.empty?
|
|
13
18
|
metadata[:"x-goog-user-project"] = @quota_project_id if @quota_project_id
|
|
14
19
|
<%- if method.routing_params? && !method.client_streaming? -%>
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<%- assert_locals method -%>
|
|
2
|
-
<%- if method.
|
|
2
|
+
<%- if method.resumable_upload? -%>
|
|
3
|
+
<%= render partial: "service/client/method/def/response_resumable_upload", locals: { method: method } -%>
|
|
4
|
+
<%- elsif method.paged? -%>
|
|
3
5
|
<%= render partial: "service/client/method/def/response_paged", locals: { method: method } -%>
|
|
4
6
|
<%- elsif method.rest.nonstandard_lro? -%>
|
|
5
7
|
<%= render partial: "service/client/method/def/response_nonstandard_lro", locals: { method: method } -%>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<%- assert_locals method -%>
|
|
2
|
+
<%- error_handler = render(partial: "service/client/method/def/upload_error_handler", locals: { method: method }).strip -%>
|
|
3
|
+
::Gapic::ResumableUpload.new(
|
|
4
|
+
client_stub_proc: -> { <%= method.service.resumable_upload_stub_ivar %>.client_stub },
|
|
5
|
+
initial_request_proc: lambda {
|
|
6
|
+
<%= method.service.resumable_upload_stub_name_full %>.<%= method.rest.transcoding_helper_name %> request
|
|
7
|
+
},
|
|
8
|
+
initial_headers: options.metadata,
|
|
9
|
+
start_retry_policy: ::Gapic::Rest::ResumableUpload.start_retry_policy_for(options),
|
|
10
|
+
response_type: <%= method.return_type %>,
|
|
11
|
+
method_name: "<%= method.name %>",
|
|
12
|
+
error_handler: <%= error_handler %>
|
|
13
|
+
)
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
<%- assert_locals method -%>
|
|
2
|
+
<%- if method.resumable_upload? -%>
|
|
3
|
+
# @overload <%= method.name %>(request = {}, options = nil)
|
|
4
|
+
# Pass arguments to `<%= method.name %>` via a request object, either of type
|
|
5
|
+
# {<%= method.request_type %>} or an equivalent Hash.
|
|
6
|
+
#
|
|
7
|
+
# @param request [<%= method.request_type %>, ::Hash]
|
|
8
|
+
# A request object representing the call parameters. Optional: it is ignored when the returned
|
|
9
|
+
# handle is resumed rather than started, because a resumed upload targets a session the server
|
|
10
|
+
# has already created.
|
|
11
|
+
# @param options [::Gapic::CallOptions, ::Hash]
|
|
12
|
+
# Overrides for the initiation request only. The `timeout`, `retry_policy` and `metadata` set
|
|
13
|
+
# here apply to the single request that creates the upload session, not to the upload as a
|
|
14
|
+
# whole: an upload still transferring bytes an hour later has long outlived this `timeout`.
|
|
15
|
+
# To bound the whole upload, pass `upload_timeout:` to {::Gapic::ResumableUpload#start} or
|
|
16
|
+
# {::Gapic::ResumableUpload#resume}. Chunk transfers are retried by the upload protocol itself,
|
|
17
|
+
# with the defaults documented on {::Gapic::ResumableUpload}; no call option reaches them.
|
|
18
|
+
# Optional.
|
|
19
|
+
<%- else -%>
|
|
2
20
|
# @overload <%= method.name %>(request, options = nil)
|
|
3
21
|
# Pass arguments to `<%= method.name %>` via a request object, either of type
|
|
4
22
|
# {<%= method.request_type %>} or an equivalent Hash.
|
|
@@ -8,6 +26,7 @@
|
|
|
8
26
|
# parameters, or to keep all the default parameter values, pass an empty Hash.
|
|
9
27
|
# @param options [::Gapic::CallOptions, ::Hash]
|
|
10
28
|
# Overrides the default settings for this call, e.g, timeout, retries, etc. Optional.
|
|
29
|
+
<%- end -%>
|
|
11
30
|
<%-if method.arguments.any?-%>
|
|
12
31
|
#
|
|
13
32
|
<%- arg_list = method.arguments.map { |arg| "#{arg.name}: nil"}.join ", " -%>
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
<%- assert_locals method -%>
|
|
2
|
+
<%- if method.resumable_upload? -%>
|
|
3
|
+
# @return [::Gapic::ResumableUpload]
|
|
4
|
+
# A reusable upload handle. No request is sent and no byte is read from a stream until
|
|
5
|
+
# {::Gapic::ResumableUpload#start} or {::Gapic::ResumableUpload#resume} is called on it.
|
|
6
|
+
# Upload failures, including a failed initiation request, are raised by those methods,
|
|
7
|
+
# not by this one.
|
|
8
|
+
<%- else -%>
|
|
2
9
|
# @yield [response, operation] Access the result along with the RPC operation
|
|
3
10
|
# @yieldparam response [<%= method.doc_response_type %>]
|
|
4
11
|
# @yieldparam operation [::GRPC::ActiveCall::Operation]
|
|
5
12
|
#
|
|
6
13
|
# @return [<%= method.doc_response_type %>]
|
|
14
|
+
<%- end -%>
|
|
@@ -21,6 +21,14 @@ require "securerandom"
|
|
|
21
21
|
<%= indent service.doc_description(transport: :rest), "# " %>
|
|
22
22
|
#
|
|
23
23
|
<%- end -%>
|
|
24
|
+
<%- if service.resumable_upload? -%>
|
|
25
|
+
<%- upload_names = service.resumable_upload_methods.map { |upload_method| "`#{upload_method.name}`" }.join ", " -%>
|
|
26
|
+
<%- upload_many = service.resumable_upload_methods.length > 1 -%>
|
|
27
|
+
# <%= upload_names %> <%= upload_many ? "perform resumable uploads: each returns" : "performs a resumable upload: it returns" %> a {::Gapic::ResumableUpload} handle
|
|
28
|
+
# instead of a response, and the per-call `timeout` and retry policy cover only the request that
|
|
29
|
+
# creates the upload session, not the upload itself.
|
|
30
|
+
#
|
|
31
|
+
<%- end -%>
|
|
24
32
|
class <%= service.rest.client_name %>
|
|
25
33
|
# @private
|
|
26
34
|
API_VERSION = "<%= service.api_version %>".freeze
|
|
@@ -141,6 +149,16 @@ class <%= service.rest.client_name %>
|
|
|
141
149
|
<%- end -%>
|
|
142
150
|
end
|
|
143
151
|
|
|
152
|
+
<%- end -%>
|
|
153
|
+
<%- if service.resumable_upload? -%>
|
|
154
|
+
<%= service.resumable_upload_stub_ivar %> = <%= service.resumable_upload_stub_name_full %>.new(
|
|
155
|
+
endpoint: @config.endpoint,
|
|
156
|
+
endpoint_template: DEFAULT_ENDPOINT_TEMPLATE,
|
|
157
|
+
universe_domain: @config.universe_domain,
|
|
158
|
+
credentials: credentials,
|
|
159
|
+
logger: @config.logger
|
|
160
|
+
)
|
|
161
|
+
|
|
144
162
|
<%- end -%>
|
|
145
163
|
@<%= service.stub_name %> = <%= service.rest.service_stub_name_full %>.new(
|
|
146
164
|
endpoint: @config.endpoint,
|
|
@@ -162,6 +162,14 @@ class Configuration
|
|
|
162
162
|
<%- method_service.rest.methods.each do |method| -%>
|
|
163
163
|
##
|
|
164
164
|
# RPC-specific configuration for `<%= method.name %>`
|
|
165
|
+
<%- if method.resumable_upload? -%>
|
|
166
|
+
#
|
|
167
|
+
# `<%= method.name %>` performs a resumable upload, so the `timeout` and `retry_policy`
|
|
168
|
+
# configured here cover the request that creates the upload session only, not the upload
|
|
169
|
+
# itself. The whole-upload budget is the `upload_timeout:` argument of
|
|
170
|
+
# {::Gapic::ResumableUpload#start} and {::Gapic::ResumableUpload#resume}.
|
|
171
|
+
#
|
|
172
|
+
<%- end -%>
|
|
165
173
|
# @return [::Gapic::Config::Method]
|
|
166
174
|
#
|
|
167
175
|
attr_reader :<%= method.name %>
|
|
@@ -7,10 +7,12 @@
|
|
|
7
7
|
<%= render partial: "service/rest/client/method/docs/request", locals: { method: method } -%>
|
|
8
8
|
<%= render partial: "service/rest/client/method/docs/result", locals: { method: method } -%>
|
|
9
9
|
#
|
|
10
|
+
<%- unless method.resumable_upload? -%>
|
|
10
11
|
<%= render partial: "service/rest/client/method/docs/error", locals: { method: method } -%>
|
|
11
12
|
#
|
|
13
|
+
<%- end -%>
|
|
12
14
|
<%= render partial: "service/rest/client/method/docs/snippets", locals: { method: method } -%>
|
|
13
|
-
def <%= method.name %> request
|
|
15
|
+
def <%= method.name %> request<%= method.resumable_upload? ? " = {}" : "" %>, options = nil
|
|
14
16
|
<%= indent render(partial: "service/client/method/def/request", locals: { method: method }), 2 %>
|
|
15
17
|
|
|
16
18
|
<%= indent render(partial: "service/rest/client/method/def/options_defaults", locals: { method: method }), 2 %>
|
|
@@ -20,5 +22,7 @@ def <%= method.name %> request, options = nil
|
|
|
20
22
|
<%- end -%>
|
|
21
23
|
|
|
22
24
|
<%= indent render(partial: "service/rest/client/method/def/response", locals: { method: method }), 2 %>
|
|
25
|
+
<%- unless method.resumable_upload? -%>
|
|
23
26
|
<%= render partial: "service/rest/client/method/def/rescue", locals: { method: method } -%>
|
|
27
|
+
<%- end -%>
|
|
24
28
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
<%- assert_locals method -%>
|
|
2
|
-
<%- if method.
|
|
2
|
+
<%- if method.resumable_upload? -%>
|
|
3
|
+
<%= render partial: "service/rest/client/method/def/response_resumable_upload", locals: { method: method } -%>
|
|
4
|
+
<%- elsif method.rest.paged? -%>
|
|
3
5
|
<%= render partial: "service/rest/client/method/def/response_paged", locals: { method: method } -%>
|
|
4
6
|
<%- elsif method.rest.nonstandard_lro? -%>
|
|
5
7
|
<%= render partial: "service/rest/client/method/def/response_nonstandard_lro", locals: { method: method } -%>
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
<%- assert_locals method -%>
|
|
2
|
+
<%- error_handler = render(partial: "service/rest/client/method/def/upload_error_handler", locals: { method: method }).strip -%>
|
|
3
|
+
::Gapic::ResumableUpload.new(
|
|
4
|
+
client_stub_proc: -> { <%= method.service.resumable_upload_stub_ivar %>.client_stub },
|
|
5
|
+
initial_request_proc: lambda {
|
|
6
|
+
<%= method.service.resumable_upload_stub_name_full %>.<%= method.rest.transcoding_helper_name %> request
|
|
7
|
+
},
|
|
8
|
+
initial_headers: options.metadata,
|
|
9
|
+
start_retry_policy: ::Gapic::Rest::ResumableUpload.start_retry_policy_for(options),
|
|
10
|
+
response_type: <%= method.return_type %>,
|
|
11
|
+
method_name: "<%= method.name %>",
|
|
12
|
+
error_handler: <%= error_handler %>
|
|
13
|
+
)
|
|
@@ -1,4 +1,22 @@
|
|
|
1
1
|
<%- assert_locals method -%>
|
|
2
|
+
<%- if method.resumable_upload? -%>
|
|
3
|
+
# @overload <%= method.name %>(request = {}, options = nil)
|
|
4
|
+
# Pass arguments to `<%= method.name %>` via a request object, either of type
|
|
5
|
+
# {<%= method.request_type %>} or an equivalent Hash.
|
|
6
|
+
#
|
|
7
|
+
# @param request [<%= method.request_type %>, ::Hash]
|
|
8
|
+
# A request object representing the call parameters. Optional: it is ignored when the returned
|
|
9
|
+
# handle is resumed rather than started, because a resumed upload targets a session the server
|
|
10
|
+
# has already created.
|
|
11
|
+
# @param options [::Gapic::CallOptions, ::Hash]
|
|
12
|
+
# Overrides for the initiation request only. The `timeout`, `retry_policy` and `metadata` set
|
|
13
|
+
# here apply to the single request that creates the upload session, not to the upload as a
|
|
14
|
+
# whole: an upload still transferring bytes an hour later has long outlived this `timeout`.
|
|
15
|
+
# To bound the whole upload, pass `upload_timeout:` to {::Gapic::ResumableUpload#start} or
|
|
16
|
+
# {::Gapic::ResumableUpload#resume}. Chunk transfers are retried by the upload protocol itself,
|
|
17
|
+
# with the defaults documented on {::Gapic::ResumableUpload}; no call option reaches them.
|
|
18
|
+
# Optional.
|
|
19
|
+
<%- else -%>
|
|
2
20
|
# @overload <%= method.name %>(request, options = nil)
|
|
3
21
|
# Pass arguments to `<%= method.name %>` via a request object, either of type
|
|
4
22
|
# {<%= method.request_type %>} or an equivalent Hash.
|
|
@@ -8,6 +26,7 @@
|
|
|
8
26
|
# parameters, or to keep all the default parameter values, pass an empty Hash.
|
|
9
27
|
# @param options [::Gapic::CallOptions, ::Hash]
|
|
10
28
|
# Overrides the default settings for this call, e.g, timeout, retries etc. Optional.
|
|
29
|
+
<%- end -%>
|
|
11
30
|
<%-if method.arguments.any?-%>
|
|
12
31
|
#
|
|
13
32
|
<%- arg_list = method.arguments.map { |arg| "#{arg.name}: nil"}.join ", " -%>
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
<%- assert_locals method -%>
|
|
2
|
-
<%- if method.
|
|
2
|
+
<%- if method.resumable_upload? -%>
|
|
3
|
+
# @return [::Gapic::ResumableUpload]
|
|
4
|
+
# A reusable upload handle. No request is sent and no byte is read from a stream until
|
|
5
|
+
# {::Gapic::ResumableUpload#start} or {::Gapic::ResumableUpload#resume} is called on it.
|
|
6
|
+
# Upload failures, including a failed initiation request, are raised by those methods,
|
|
7
|
+
# not by this one.
|
|
8
|
+
<%- elsif method.server_streaming? -%>
|
|
3
9
|
# @return [::Enumerable<<%= method.rest.doc_response_type %>>]
|
|
4
10
|
<%- else -%>
|
|
5
11
|
# @yield [result, operation] Access the result along with the TransportOperation object
|
|
@@ -52,11 +52,11 @@ class <%= service.rest.service_stub_name %>
|
|
|
52
52
|
stub ? @client_stub.stub_logger : @client_stub.logger
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
<%- service.rest.
|
|
55
|
+
<%- service.rest.service_stub_methods.each do |method| -%>
|
|
56
56
|
<%= indent_tail render(partial: "service/rest/service_stub/method/def", locals: { method: method, service_stub_name: service.rest.service_stub_name }), 2 %>
|
|
57
57
|
|
|
58
58
|
<%- end %>
|
|
59
|
-
<%- service.rest.
|
|
59
|
+
<%- service.rest.service_stub_methods.each do |method| -%>
|
|
60
60
|
<%= indent_tail render(partial: "service/rest/service_stub/grpc_transcoding_method/def", locals: { method: method }), 2 %>
|
|
61
61
|
|
|
62
62
|
<%- end %>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<%- assert_locals method -%>
|
|
2
|
+
<%- method.http_bindings.each do |http_binding| -%>
|
|
3
|
+
.with_bindings(
|
|
4
|
+
uri_method: :<%= http_binding.verb %>,
|
|
5
|
+
uri_template: "<%= http_binding.uri_for_transcoding %>",
|
|
6
|
+
<%- if http_binding.body? -%>
|
|
7
|
+
body: "<%= http_binding.body %>",
|
|
8
|
+
<%- end -%>
|
|
9
|
+
matches: [
|
|
10
|
+
<%- http_binding.routing_params_transcoder_matches_strings.each do |match_str| -%>
|
|
11
|
+
<%= match_str %>
|
|
12
|
+
<%- end -%>
|
|
13
|
+
]
|
|
14
|
+
)
|
|
15
|
+
<%- end -%>
|
|
@@ -19,19 +19,6 @@ def self.<%= method.rest.transcoding_helper_name %> request_pb<%= boverr_str %>
|
|
|
19
19
|
<%- end %>
|
|
20
20
|
<%- assignment = method.service.rest.is_main_mixin_service? ? "||=" : "=" -%>
|
|
21
21
|
transcoder <%= assignment %> Gapic::Rest::GrpcTranscoder.new
|
|
22
|
-
|
|
23
|
-
.with_bindings(
|
|
24
|
-
uri_method: :<%= http_binding.verb %>,
|
|
25
|
-
uri_template: "<%= http_binding.uri_for_transcoding %>",
|
|
26
|
-
<%- if http_binding.body? -%>
|
|
27
|
-
body: "<%= http_binding.body %>",
|
|
28
|
-
<%- end -%>
|
|
29
|
-
matches: [
|
|
30
|
-
<%- http_binding.routing_params_transcoder_matches_strings.each do |match_str| -%>
|
|
31
|
-
<%= match_str %>
|
|
32
|
-
<%- end -%>
|
|
33
|
-
]
|
|
34
|
-
)
|
|
35
|
-
<%- end %>
|
|
22
|
+
<%= indent render(partial: "service/rest/service_stub/grpc_transcoding_method/bindings", locals: { method: method }), 44 %>
|
|
36
23
|
transcoder.transcode request_pb
|
|
37
24
|
end
|
|
@@ -9,7 +9,7 @@ require "<%= service.rest.service_require %>"
|
|
|
9
9
|
class <%= service.rest.client_name_full %>Test < Minitest::Test
|
|
10
10
|
<%= indent render(partial: "service/rest/test/method/setup"), 2 %>
|
|
11
11
|
|
|
12
|
-
<% service.rest.methods.each do |method| %>
|
|
12
|
+
<% service.rest.methods.reject(&:resumable_upload?).each do |method| %>
|
|
13
13
|
<%= indent render(partial: "service/rest/test/method/#{method.kind}",
|
|
14
14
|
locals: { method: method }), 2 %>
|
|
15
15
|
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
<%- assert_locals service -%>
|
|
2
|
+
##
|
|
3
|
+
# Resumable upload stub for the <%= service.name %> service.
|
|
4
|
+
#
|
|
5
|
+
# Owns the REST client stub the uploads are performed through, the transcoders that build their
|
|
6
|
+
# initiation requests, and the credentials error that a client unable to perform REST calls has to
|
|
7
|
+
# raise when an upload is attempted.
|
|
8
|
+
#
|
|
9
|
+
# @private
|
|
10
|
+
#
|
|
11
|
+
class <%= service.resumable_upload_stub_name %>
|
|
12
|
+
<%- service.resumable_upload_methods.each do |method| -%>
|
|
13
|
+
# @private
|
|
14
|
+
<%= method.upload_url_prefix_const_name %> = "<%= method.upload_url_prefix %>"
|
|
15
|
+
|
|
16
|
+
<%- end -%>
|
|
17
|
+
# @private
|
|
18
|
+
def initialize endpoint:, endpoint_template:, universe_domain:, credentials:, logger:
|
|
19
|
+
# These require statements are intentionally placed here to initialize
|
|
20
|
+
# the REST modules only when it's required.
|
|
21
|
+
require "gapic/rest"
|
|
22
|
+
|
|
23
|
+
# Uploads travel over REST, and credentials cannot be recovered from a gRPC channel. Rather than
|
|
24
|
+
# raise while a client is being constructed, which would break every other method on it, the
|
|
25
|
+
# error is stored and raised when an upload is actually attempted.
|
|
26
|
+
if defined?(::GRPC::Core::Channel) &&
|
|
27
|
+
(credentials.is_a?(::GRPC::Core::Channel) || credentials.is_a?(::GRPC::Core::ChannelCredentials))
|
|
28
|
+
@credentials_error = ::ArgumentError.new(
|
|
29
|
+
"Resumable uploads are performed over REST and cannot use a gRPC channel as credentials, " \
|
|
30
|
+
"because credentials cannot be recovered from a channel. Construct the client with Google " \
|
|
31
|
+
"OAuth credentials (a keyfile path, a Hash, or a Google::Auth::Credentials instance) to use " \
|
|
32
|
+
"resumable upload methods."
|
|
33
|
+
)
|
|
34
|
+
return
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
@client_stub = ::Gapic::Rest::ClientStub.new endpoint: endpoint,
|
|
38
|
+
endpoint_template: endpoint_template,
|
|
39
|
+
universe_domain: universe_domain,
|
|
40
|
+
credentials: credentials,
|
|
41
|
+
numeric_enums: false,
|
|
42
|
+
service_name: self.class,
|
|
43
|
+
raise_faraday_errors: false,
|
|
44
|
+
logger: logger
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
##
|
|
48
|
+
# @private
|
|
49
|
+
#
|
|
50
|
+
# The REST client stub the uploads are performed through.
|
|
51
|
+
#
|
|
52
|
+
# @return [::Gapic::Rest::ClientStub]
|
|
53
|
+
#
|
|
54
|
+
# @raise [::ArgumentError] if this client cannot perform REST calls.
|
|
55
|
+
#
|
|
56
|
+
def client_stub
|
|
57
|
+
raise @credentials_error if @credentials_error
|
|
58
|
+
@client_stub
|
|
59
|
+
end
|
|
60
|
+
<%- service.resumable_upload_methods.each do |method| -%>
|
|
61
|
+
|
|
62
|
+
<%= indent_tail render(partial: "service/resumable_upload_stub/transcoding_method", locals: { method: method, service: service }), 2 %>
|
|
63
|
+
<%- end -%>
|
|
64
|
+
end
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
<%- assert_locals method, service -%>
|
|
2
|
+
##
|
|
3
|
+
# @private
|
|
4
|
+
#
|
|
5
|
+
# GRPC transcoding helper method for the <%= method.name %> resumable upload initiation request.
|
|
6
|
+
#
|
|
7
|
+
# The upload itself is not transcoded: only the request that creates the upload session is, and the
|
|
8
|
+
# verb is discarded because initiation is always a POST. Query string parameters are folded into the
|
|
9
|
+
# URL, since the upload sends the initiation request with no separate parameters.
|
|
10
|
+
#
|
|
11
|
+
# @param request_pb [<%= method.request_type %>]
|
|
12
|
+
# A request object representing the call parameters. Required.
|
|
13
|
+
# @return [Array(String, [String, nil])]
|
|
14
|
+
# Uri, Body
|
|
15
|
+
def self.<%= method.rest.transcoding_helper_name %> request_pb
|
|
16
|
+
transcoder = ::Gapic::Rest::GrpcTranscoder.new
|
|
17
|
+
<%= indent render(partial: "service/rest/service_stub/grpc_transcoding_method/bindings", locals: { method: method }), 46 %>
|
|
18
|
+
_verb, uri, query_string_params, body = transcoder.transcode request_pb
|
|
19
|
+
uri = "/#{<%= method.upload_url_prefix_const_name %>}#{uri}"
|
|
20
|
+
uri = "#{uri}?#{query_string_params.join '&'}" if query_string_params.any?
|
|
21
|
+
[uri, body]
|
|
22
|
+
end
|
|
@@ -10,7 +10,7 @@ require "<%= service.service_require %>"
|
|
|
10
10
|
class <%= service.client_name_full %>Test < Minitest::Test
|
|
11
11
|
<%= indent render(partial: "service/test/method/setup"), 2 %>
|
|
12
12
|
|
|
13
|
-
<% service.methods.each do |method| %>
|
|
13
|
+
<% service.methods.reject(&:resumable_upload?).each do |method| %>
|
|
14
14
|
<%= indent render(partial: "service/test/method/#{method.kind}",
|
|
15
15
|
locals: { method: method }), 2 %>
|
|
16
16
|
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
<%- assert_locals service -%>
|
|
2
|
+
<%= render partial: "shared/header" %>
|
|
3
|
+
require "helper"
|
|
4
|
+
|
|
5
|
+
require "gapic/rest"
|
|
6
|
+
<%- if service.generate_grpc_clients? -%>
|
|
7
|
+
require "gapic/grpc/service_stub"
|
|
8
|
+
<%- end -%>
|
|
9
|
+
|
|
10
|
+
require "<%= service.proto_service_require %>"
|
|
11
|
+
<%- if service.generate_grpc_clients? -%>
|
|
12
|
+
require "<%= service.service_require %>"
|
|
13
|
+
<%- end -%>
|
|
14
|
+
<%- if service.generate_rest_clients? -%>
|
|
15
|
+
require "<%= service.rest.service_require %>"
|
|
16
|
+
<%- end -%>
|
|
17
|
+
|
|
18
|
+
class <%= service.service_name_full %>::ResumableUploadTest < Minitest::Test
|
|
19
|
+
##
|
|
20
|
+
# Stands in for the transport stub a client builds in its constructor. An upload method sends
|
|
21
|
+
# nothing, so this only has to satisfy the constructor.
|
|
22
|
+
#
|
|
23
|
+
class ClientStub
|
|
24
|
+
def endpoint
|
|
25
|
+
"endpoint.example.com"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def universe_domain
|
|
29
|
+
"example.com"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def stub_logger
|
|
33
|
+
nil
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def logger
|
|
37
|
+
nil
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
<%- service.resumable_upload_methods.each do |method| -%>
|
|
41
|
+
<%- fields = method.fields_with_first_oneof -%>
|
|
42
|
+
<%- prefix_const = "#{service.resumable_upload_stub_name_full}::#{method.upload_url_prefix_const_name}" -%>
|
|
43
|
+
|
|
44
|
+
def test_transcode_<%= method.name %>_request
|
|
45
|
+
request = <%= method.request_type %>.new
|
|
46
|
+
|
|
47
|
+
# The transcoder is stubbed so the test pins the upload-specific post-processing (prefix,
|
|
48
|
+
# query-string folding, [uri, body] shape) independently of the method's path template.
|
|
49
|
+
transcoder = Gapic::Rest::GrpcTranscoder.new
|
|
50
|
+
transcoder.stub :transcode, [:post, "/transcoded/path", ["foo=bar", "baz=qux"], "{\"body\":true}"] do
|
|
51
|
+
Gapic::Rest::GrpcTranscoder.stub :new, transcoder do
|
|
52
|
+
uri, body = <%= service.resumable_upload_stub_name_full %>.<%= method.rest.transcoding_helper_name %> request
|
|
53
|
+
|
|
54
|
+
assert_equal "/#{<%= prefix_const %>}/transcoded/path?foo=bar&baz=qux", uri
|
|
55
|
+
assert_equal "{\"body\":true}", body
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
<%- if service.generate_grpc_clients? -%>
|
|
60
|
+
|
|
61
|
+
def test_<%= method.name %>
|
|
62
|
+
<%- fields.each do |field| -%>
|
|
63
|
+
<%= field.value_name %> = <%= field.default_value %>
|
|
64
|
+
<%- end -%>
|
|
65
|
+
|
|
66
|
+
client = nil
|
|
67
|
+
Gapic::ServiceStub.stub :new, ClientStub.new do
|
|
68
|
+
client = <%= service.client_name_full %>.new do |config|
|
|
69
|
+
config.credentials = :this_channel_is_insecure
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
upload = client.<%= method.name %> <%= method.request_type %>.new(<%= fields.map(&:as_kwarg).join ", " %>)
|
|
74
|
+
|
|
75
|
+
# The call builds a handle and sends nothing. The upload only begins on #start or #resume.
|
|
76
|
+
assert_kind_of ::Gapic::ResumableUpload, upload
|
|
77
|
+
assert_nil upload.resume_handle
|
|
78
|
+
refute upload.resumable?
|
|
79
|
+
refute upload.running?
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def test_<%= method.name %>_channel_credentials
|
|
83
|
+
<%- fields.each do |field| -%>
|
|
84
|
+
<%= field.value_name %> = <%= field.default_value %>
|
|
85
|
+
<%- end -%>
|
|
86
|
+
grpc_channel = GRPC::Core::Channel.new "localhost:8888", nil, :this_channel_is_insecure
|
|
87
|
+
|
|
88
|
+
client = nil
|
|
89
|
+
Gapic::ServiceStub.stub :new, ClientStub.new do
|
|
90
|
+
client = <%= service.client_name_full %>.new do |config|
|
|
91
|
+
config.credentials = grpc_channel
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
upload = client.<%= method.name %> <%= method.request_type %>.new(<%= fields.map(&:as_kwarg).join ", " %>)
|
|
96
|
+
|
|
97
|
+
assert_kind_of ::Gapic::ResumableUpload, upload
|
|
98
|
+
|
|
99
|
+
# Uploads travel over REST and cannot use a channel as credentials. The error surfaces here,
|
|
100
|
+
# rather than at construction, and before the stream is touched.
|
|
101
|
+
stream = StringIO.new "resumable upload test payload"
|
|
102
|
+
assert_raises ::ArgumentError do
|
|
103
|
+
upload.start stream: stream, content_type: "application/octet-stream"
|
|
104
|
+
end
|
|
105
|
+
assert_equal 0, stream.pos
|
|
106
|
+
end
|
|
107
|
+
<%- end -%>
|
|
108
|
+
<%- if service.generate_rest_clients? -%>
|
|
109
|
+
|
|
110
|
+
def test_<%= method.name %>_rest
|
|
111
|
+
<%- fields.each do |field| -%>
|
|
112
|
+
<%= field.value_name %> = <%= field.default_value %>
|
|
113
|
+
<%- end -%>
|
|
114
|
+
|
|
115
|
+
client = nil
|
|
116
|
+
Gapic::Rest::ClientStub.stub :new, ClientStub.new do
|
|
117
|
+
client = <%= service.rest.client_name_full %>.new do |config|
|
|
118
|
+
config.credentials = :dummy_value
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
upload = client.<%= method.name %> <%= method.request_type %>.new(<%= fields.map(&:as_kwarg).join ", " %>)
|
|
123
|
+
|
|
124
|
+
# The call builds a handle and sends nothing. The upload only begins on #start or #resume.
|
|
125
|
+
assert_kind_of ::Gapic::ResumableUpload, upload
|
|
126
|
+
assert_nil upload.resume_handle
|
|
127
|
+
refute upload.resumable?
|
|
128
|
+
refute upload.running?
|
|
129
|
+
end
|
|
130
|
+
<%- end -%>
|
|
131
|
+
<%- end -%>
|
|
132
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: gapic-generator
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.53.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ernest Landrito
|
|
@@ -150,6 +150,7 @@ files:
|
|
|
150
150
|
- lib/gapic/model/api_metadata.rb
|
|
151
151
|
- lib/gapic/model/method/http_annotation.rb
|
|
152
152
|
- lib/gapic/model/method/lro.rb
|
|
153
|
+
- lib/gapic/model/method/resumable_upload.rb
|
|
153
154
|
- lib/gapic/model/method/routing.rb
|
|
154
155
|
- lib/gapic/model/mixins.rb
|
|
155
156
|
- lib/gapic/model/model_error.rb
|
|
@@ -267,7 +268,9 @@ files:
|
|
|
267
268
|
- templates/default/service/client/method/def/_response_normal.text.erb
|
|
268
269
|
- templates/default/service/client/method/def/_response_normal_lro.text.erb
|
|
269
270
|
- templates/default/service/client/method/def/_response_paged.text.erb
|
|
271
|
+
- templates/default/service/client/method/def/_response_resumable_upload.text.erb
|
|
270
272
|
- templates/default/service/client/method/def/_routing_params.text.erb
|
|
273
|
+
- templates/default/service/client/method/def/_upload_error_handler.text.erb
|
|
271
274
|
- templates/default/service/client/method/docs/_error.text.erb
|
|
272
275
|
- templates/default/service/client/method/docs/_request.text.erb
|
|
273
276
|
- templates/default/service/client/method/docs/_request_field.text.erb
|
|
@@ -306,7 +309,9 @@ files:
|
|
|
306
309
|
- templates/default/service/rest/client/method/def/_response_normal.text.erb
|
|
307
310
|
- templates/default/service/rest/client/method/def/_response_normal_lro.text.erb
|
|
308
311
|
- templates/default/service/rest/client/method/def/_response_paged.text.erb
|
|
312
|
+
- templates/default/service/rest/client/method/def/_response_resumable_upload.text.erb
|
|
309
313
|
- templates/default/service/rest/client/method/def/_response_server_streaming.text.erb
|
|
314
|
+
- templates/default/service/rest/client/method/def/_upload_error_handler.text.erb
|
|
310
315
|
- templates/default/service/rest/client/method/docs/_error.text.erb
|
|
311
316
|
- templates/default/service/rest/client/method/docs/_request.text.erb
|
|
312
317
|
- templates/default/service/rest/client/method/docs/_result.text.erb
|
|
@@ -316,6 +321,7 @@ files:
|
|
|
316
321
|
- templates/default/service/rest/operations.text.erb
|
|
317
322
|
- templates/default/service/rest/service_stub.text.erb
|
|
318
323
|
- templates/default/service/rest/service_stub/_service_stub.text.erb
|
|
324
|
+
- templates/default/service/rest/service_stub/grpc_transcoding_method/_bindings.text.erb
|
|
319
325
|
- templates/default/service/rest/service_stub/grpc_transcoding_method/_def.text.erb
|
|
320
326
|
- templates/default/service/rest/service_stub/grpc_transcoding_method/def/_query_string_param.text.erb
|
|
321
327
|
- templates/default/service/rest/service_stub/method/_def.text.erb
|
|
@@ -327,6 +333,9 @@ files:
|
|
|
327
333
|
- templates/default/service/rest/test/method/_normal.text.erb
|
|
328
334
|
- templates/default/service/rest/test/method/_server.text.erb
|
|
329
335
|
- templates/default/service/rest/test/method/_setup.text.erb
|
|
336
|
+
- templates/default/service/resumable_upload_stub.text.erb
|
|
337
|
+
- templates/default/service/resumable_upload_stub/_resumable_upload_stub.text.erb
|
|
338
|
+
- templates/default/service/resumable_upload_stub/_transcoding_method.text.erb
|
|
330
339
|
- templates/default/service/test/_resource.text.erb
|
|
331
340
|
- templates/default/service/test/client.text.erb
|
|
332
341
|
- templates/default/service/test/client_operations.text.erb
|
|
@@ -338,6 +347,7 @@ files:
|
|
|
338
347
|
- templates/default/service/test/method/_normal.text.erb
|
|
339
348
|
- templates/default/service/test/method/_server.text.erb
|
|
340
349
|
- templates/default/service/test/method/_setup.text.erb
|
|
350
|
+
- templates/default/service/test/resumable_upload.text.erb
|
|
341
351
|
- templates/default/service/test/smoke.text.erb
|
|
342
352
|
- templates/default/shared/_header.text.erb
|
|
343
353
|
- templates/default/shared/_license.text.erb
|