Skip to content

build: drop the gRPC transport that google-cloud-storage never uses here - #200

Merged
marevol merged 1 commit into
masterfrom
build/exclude-gcs-grpc
Sep 9, 2026
Merged

marevol merged 1 commit into
masterfrom
build/exclude-gcs-grpc

Conversation

@marevol

@marevol marevol commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Why

google-cloud-storage ships two transports and declares the dependencies of both.
GcsClient and the gcs: URL handler both build their client with
StorageOptions.newBuilder(), which is the JSON-over-HTTP transport; the gRPC one is
reachable only through StorageOptions.grpc(), which nothing calls. Its stack was on the
classpath anyway, and in every artifact that depends on fess-crawler:

29 jars, 26.4 MiB removed, nothing added. grpc-xds (10.5 MiB) and
grpc-netty-shaded (10.3 MiB) are 21 MiB of that between them.

Three things deliberately kept

Each of these looks like part of the gRPC stack and is not:

Kept Why
io.grpc:grpc-api HttpStorageRpc#startSpan opens an OpenCensus span on every request, and OpenCensus keeps its current span in io.grpc.Context — which has lived in grpc-api since gRPC 1.60. The grpc-context artifact still exists but no longer holds the class.
proto-google-cloud-storage-v2 JsonConversions#bucketInfoDecode uses com.google.storage.v2.BucketName. The v2 protos are shared between the transports.
opentelemetry-api, -context, -common gax-httpjson uses them.

Both of the first two were found by running the tests, not by reading the dependency
tree.
A first attempt excluded io.grpc:* and proto-google-cloud-storage-v2; that
compiles clean and then throws on the first call:

java.lang.NoClassDefFoundError: io/grpc/Context
  at io.opencensus.trace.unsafe.ContextManagerImpl.currentContext
  ...
  at com.google.cloud.storage.spi.v1.HttpStorageRpc.startSpan(HttpStorageRpc.java:384)

java.lang.NoClassDefFoundError: com/google/storage/v2/BucketName
  at com.google.cloud.storage.Utils.lambda$static$4(Utils.java:155)
  at com.google.cloud.storage.JsonConversions.bucketInfoDecode(JsonConversions.java:613)

Worth knowing for anyone reviewing a similar change: compile-clean says nothing here.

Why the OpenTelemetry SDK and the generated gRPC client are safe

Not by argument — by reading the constant pools of the classes in
google-cloud-storage-2.71.0.jar:

  • Exactly one class references io/opentelemetry/sdk or
    com/google/cloud/opentelemetry: OpenTelemetryBootstrappingUtils. Its only caller in
    the jar is GrpcStorageOptions.
  • Every class referencing com/google/storage/v2/StorageClient is either a Grpc* class
    or a BlobWriteSessionConfig factory, which only a caller asking for gRPC uploads
    reaches.

Verification

mvn test2057 tests, 0 failures, 0 errors, BUILD SUCCESS, including
GcsClientTest (7 tests) against fsouza/fake-gcs-server via testcontainers, which
exercises create, doGet and doHead over the real JSON API.

Note for the Fess side

Fess declares google-cloud-storage directly too, so these exclusions do not reach it;
codelibs/fess needs the same block. That is a separate PR.

google-cloud-storage ships two transports and declares the dependencies of both.
GcsClient and the gcs: URL handler both build their client with
StorageOptions.newBuilder(), which is the JSON over HTTP transport; the gRPC one
is reachable only through StorageOptions.grpc(), which nothing calls. Its stack
was still on the classpath and in every artifact that depends on this: 29 jars,
26.4 MiB, of which grpc-xds and grpc-netty-shaded are 21 MiB between them.

Excluded: the gRPC runtime, gax-grpc, google-cloud-core-grpc, the generated gRPC
storage client, the OpenTelemetry SDK, and google-cloud-monitoring with its
protos, which are there for gRPC's client-side metrics.

Three things stay, each because removing them breaks the JSON transport:

- io.grpc:grpc-api. HttpStorageRpc#startSpan opens an OpenCensus span on every
  request, and OpenCensus keeps its current span in io.grpc.Context, which has
  lived in grpc-api since gRPC 1.60 -- the grpc-context artifact still exists but
  no longer holds the class. Excluding it threw NoClassDefFoundError on the first
  call.
- proto-google-cloud-storage-v2. JsonConversions#bucketInfoDecode uses
  com.google.storage.v2.BucketName, so the v2 protos are shared between the two
  transports rather than belonging to the gRPC one.
- opentelemetry api, context and common, which gax-httpjson uses.

Both of those failures were found by running the tests, not by reading the
dependency tree: the tree gives no hint that the JSON path reaches into either.

What made the OpenTelemetry SDK safe to remove is that the only class in
google-cloud-storage referencing it -- OpenTelemetryBootstrappingUtils -- has
exactly one caller in the jar, GrpcStorageOptions. The same holds for the
generated gRPC client: every class referencing com.google.storage.v2.StorageClient
is either a Grpc* class or a BlobWriteSessionConfig factory that only a caller
asking for gRPC uploads reaches.

Verified with the full suite, 2057 tests, including GcsClientTest against
fsouza/fake-gcs-server.
marevol added a commit to codelibs/fess that referenced this pull request Sep 9, 2026
…ere (#3415)

GcsStorageClient builds its client with StorageOptions.newBuilder(), which is the
JSON over HTTP transport. The gRPC one is reachable only through
StorageOptions.grpc(), which nothing calls, but google-cloud-storage declares the
dependencies of both, so the distribution carried the whole gRPC stack: 29 jars,
26.4 MiB, of which grpc-xds and grpc-netty-shaded are 21 MiB between them.

The exclusion block is the same one as codelibs/fess-crawler#200. Fess declares
google-cloud-storage directly, so the exclusions there do not reach it.

Three things stay because removing them breaks the JSON transport: io.grpc:grpc-api,
which holds io.grpc.Context that OpenCensus needs on every request;
proto-google-cloud-storage-v2, which JsonConversions decodes bucket names with; and
the OpenTelemetry api, context and common jars, which gax-httpjson uses.
@marevol
marevol added this pull request to stack #202 September 9, 2026 12:29
@marevol marevol self-assigned this Sep 9, 2026
@marevol marevol added this to the 15.9.0 milestone Sep 9, 2026
@marevol
marevol merged commit a0c10f5 into master Sep 9, 2026
1 check passed
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.

1 participant