Skip to content

feat(generator): emit resumable upload settings and HttpJson upload stub - #14321

Draft
whowes wants to merge 1 commit into
mainfrom
whowes/generator-resumable-upload-stub-composer
Draft

whowes wants to merge 1 commit into
mainfrom
whowes/generator-resumable-upload-stub-composer

Conversation

@whowes

@whowes whowes commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

Modified and introduces composers to emit an internal, dedicated REST stub and settings for resumable upload-powered services

@whowes
whowes added this pull request to stack #14327 September 9, 2026 06:35
gemini-code-assist[bot]

This comment was marked as outdated.

@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from f246196 to 1885bb8 Compare September 9, 2026 15:50
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from 1885bb8 to 542f6e7 Compare September 9, 2026 20:16
@whowes
whowes removed this pull request from stack #14327 September 9, 2026 23:45
@whowes
whowes added this pull request to stack #14343 September 9, 2026 23:47
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from 542f6e7 to 6f00489 Compare September 9, 2026 23:51
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from 6f00489 to 296ed15 Compare September 10, 2026 00:19
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from 296ed15 to bbc408e Compare September 10, 2026 01:15
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from bbc408e to c8c1e06 Compare September 10, 2026 06:05
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from c8c1e06 to c41b295 Compare September 11, 2026 17:24
@whowes
whowes removed this pull request from stack #14343 September 11, 2026 17:25
@whowes
whowes added this pull request to stack #14363 September 11, 2026 17:25
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from c41b295 to 63a3b57 Compare September 11, 2026 18:30
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from 63a3b57 to f014476 Compare September 11, 2026 20:00
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from f014476 to 46d6fdf Compare September 11, 2026 21:14
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from 46d6fdf to 2525926 Compare September 11, 2026 21:39
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from 2525926 to 2f42f31 Compare September 11, 2026 22:15
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from 2f42f31 to 15511ad Compare September 14, 2026 21:34
new HttpJsonServiceResumableUploadStubClassComposer();

private static final Statement EMPTY_LINE_STATEMENT = EmptyLineStatement.create();
private static final String RESUMABLE_UPLOAD_PATH_PREFIX = "resumable/upload";

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this hardcoded for Ads/Showcase?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this milestone the prefix is hardcoded. The requirement is to make it configurable in the next milestone.

import org.jspecify.annotations.NullMarked;

@NullMarked
public class HttpJsonServiceResumableUploadStubClassComposer implements ClassComposer {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to extend from AbstractTransportServiceStubClassComposer? Generation logics for methods like close, shutdown should be able to be reused.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up extracting the shared functionality to a common helper. Extending AbstractTransportServiceStubClassComposer seemed like an awkward fit because it's intended to generate the entire service stub (including stuff for LROs, pagination, etc.) whereas this stub is a much more narrow scope.

public class HttpJsonResumableUploadServiceResumableUploadStub implements BackgroundResource {
private static final TypeRegistry typeRegistry = TypeRegistry.newBuilder().build();

private static final ApiMethodDescriptor<UploadMediaRequest, UploadMediaResponse>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC, the ApiMethodDescriptor here is only used for startUpload?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's mostly for startUpload, though the response parser is used for the other resumable upload commands.

@whowes
whowes removed this pull request from stack #14363 September 14, 2026 22:18
@whowes
whowes added this pull request to stack #14381 September 14, 2026 22:19
@whowes
whowes removed this pull request from stack #14381 September 14, 2026 23:13
@whowes
whowes added this pull request to stack #14382 September 14, 2026 23:14
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch 2 times, most recently from ec75b25 to f772f86 Compare September 15, 2026 16:30
@whowes
whowes removed this pull request from stack #14382 September 15, 2026 16:40
@whowes
whowes changed the base branch from whowes/generator-rest-composer-helpers to main September 15, 2026 16:45
@whowes whowes changed the title feat(generator): add HttpJsonServiceResumableUploadStubClassComposer feat(generator): emit resumable upload settings and HttpJson upload stub Sep 15, 2026
@whowes
whowes added this pull request to stack #14390 September 15, 2026 16:48
*/
public static HttpJsonResumableUploadServiceResumableUploadStub createFrom(
ClientContext clientContext, ResumableUploadServiceStubSettings settings) {
String uploadEndpoint =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe create a new clientContext using ClientContext.create(settings)? So we don't have to manually re-create the clientContext from existing clientContext?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After more investigation, I think ClientContext.create(settings) should work for httpjson stub without any issues. For grpc stub, we need to recreate the settings with a default internal header provider and httpjson channel, then ClientContext.create(settings) should work.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmmm, I guess I'm not seeing how calling ClientContext.create(settings) inside the upload stub without referencing the parent context can avoid at least two main issues:

  • for both transports, in the top-level stub layer's create(ClientContext) factory overload, settings is just <Service>StubSettings.newBuilder().build(), so if we re-create from settings then everything caller-supplied on the ClientContext is dropped. We'd also be creating a separate thread pool and doing another ADC lookup on every client instance (even on REST stubs that already built an HTTP ClientContext- this I guess isn't functionally a problem, just suboptimal).
  • we can't swap the gRPC internal headers (x-goog-api-client: ... grpc/...) for HTTP headers via settings.toBuilder() because StubSettings.Builder#setInternalHeaderProvider is protected and in a different package (unless you think it's worth widening it for this, but the above issue still seems like a blocker alone)

* settings. This is protected so that it is easy to make a subclass, but otherwise, the static
* factory methods should be preferred.
*/
protected HttpJsonResumableUploadServiceResumableUploadStub(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have three constructor/factory methods that have the same arguments, consider consolidate them.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Modified this to have one private constructor and one factory method (which has a conditional to adapt for gRPC v. HTTP/JSON).

@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch 3 times, most recently from 57daa1f to 954089e Compare September 16, 2026 00:45
}

@InternalApi
public static List<ApiMethodDescriptor> getMethodDescriptors() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need this public method? I think this is only used in tests and we don't have to generate unit tests anymore.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look like it's necessary - removed.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need unit tests for these composers unless we think there are logics that are hard to test with goldens.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems reasonable, removed.

RetrySettings settings = null;
settings = RetrySettings.newBuilder().setRpcTimeoutMultiplier(1.0).build();
definitions.put("no_retry_params", settings);
RETRY_PARAM_DEFINITIONS = definitions.build();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The retry settings are not used currently, we need to add the initial unary call settings to ResumableUploadCallSettings. I'll work on it in a separate PR.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SGTM, thanks!

Adds generator support for protocol-specific resumable upload options, independent of any transport stub wiring:

- Emit ResumableUploadCallSettings on the generated <Service>Settings and
  <Service>StubSettings, populated with global timeouts extracted from the
  service config while bypassing standard unary retries.
- Add HttpJsonServiceResumableUploadStubClassComposer, which generates the
  dedicated REST stub (HttpJson[Service]ResumableUploadStub) for services
  containing resumable upload RPC methods.
- Extract HttpJsonDescriptorComposer out of HttpJsonServiceStubClassComposer
  and add path prefix support. Pure refactor with no golden changes, reused by
  the upload stub composer above.

Supersedes #14318 and #14320, which are folded in here.
@whowes
whowes force-pushed the whowes/generator-resumable-upload-stub-composer branch from 954089e to 5821e21 Compare September 16, 2026 05:46
@sonarqubecloud

Copy link
Copy Markdown

@sonarqubecloud

Copy link
Copy Markdown

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants