gRPC support for opensearch-java#2062
Open
dayana-j wants to merge 18 commits into
Open
Conversation
dayana-j
requested review from
Bukhtawar,
VachaShah,
Xtansia,
madhusudhankonda,
reta,
saratvemulapalli and
szczepanczykd
as code owners
July 15, 2026 17:46
dayana-j
force-pushed
the
grpc-java
branch
2 times, most recently
from
July 15, 2026 17:51
5e44f37 to
cc3185c
Compare
dayana-j
marked this pull request as draft
July 15, 2026 17:52
dayana-j
marked this pull request as ready for review
July 15, 2026 18:44
Adds a transparent gRPC transport layer that routes bulk operations over gRPC for improved performance while falling back to REST for all other operations. Isolated in a separate java-client-grpc module to prevent classpath conflicts. Includes: - GrpcTransport + HybridTransport (automatic routing and fallback) - Translation layer (BulkRequest/Response <-> protobuf conversion) - TLS support (trust cert, trust store, mTLS, insecure, hostname override) - Basic auth, AWS SigV4, and JWT authentication interceptors - Channel health monitoring via gRPC connectivity state machine - Integration tests (framework-compliant, version-gated to 3.5.0+) - Sample code and CI configuration Signed-off-by: Dayana Jean <jeadayao@amazon.com>
Signed-off-by: Dayana Jean <jeadayao@amazon.com>
I think if we encounter some gRPC error we should explicitly propagate this back to the user instead of silently falling back to REST here. |
reta
reviewed
Jul 18, 2026
reta
reviewed
Jul 18, 2026
reta
reviewed
Jul 18, 2026
reta
reviewed
Jul 18, 2026
reta
reviewed
Jul 18, 2026
reta
reviewed
Jul 18, 2026
reta
reviewed
Jul 18, 2026
reta
reviewed
Jul 18, 2026
reta
reviewed
Jul 18, 2026
reta
reviewed
Jul 18, 2026
reta
reviewed
Jul 18, 2026
Collaborator
|
Thanks @dayana-j , good one, did a first pass, look very solid in general! Could you please also add OpenSearch 3.5.0 (or 3.6.0) to the test matrix here |
Co-authored-by: Andriy Redko <drreta@gmail.com> Signed-off-by: Dayana <jeandayana28@gmail.com>
Apply suggestion from @reta Co-authored-by: Andriy Redko <drreta@gmail.com> Signed-off-by: Dayana <jeandayana28@gmail.com>
Apply suggestion from @reta Co-authored-by: Andriy Redko <drreta@gmail.com> Signed-off-by: Dayana <jeandayana28@gmail.com>
…ivate classes - Removed GrpcStatusConverter.toHttpStatus() which was unused anywhere in the codebase (per maintainer feedback) - Moved TranslationTest to the translation package so it can access package-private FieldMappingUtil and GrpcStatusConverter.convert() Signed-off-by: Dayana Jean <jeadayao@amazon.com>
Follows the same pattern as ApacheHttpClient5Transport (general) vs AwsSdk2Transport (AWS-specific) in the existing codebase. Changes: - Created AwsGrpcTransport: extends GrpcTransport, adds SigV4 signing - AwsGrpcTransport.awsBuilder(host, port).sigV4(...).tls(...).build() - Requires sigV4Config and TLS - Overrides preProcessBulk() for payload hash computation - Removed SigV4 from GrpcTransport: - Removed .sigV4() builder method - Removed sigV4Interceptor field - Added protected preProcessBulk() hook for subclasses - GrpcTransport is now purely general-purpose (basic auth, JWT, TLS) - Updated tests to use AwsGrpcTransport for SigV4 tests Signed-off-by: Dayana Jean <jeadayao@amazon.com>
Per maintainer feedback: if the intent is to use gRPC for a supported endpoint, errors should propagate to the user rather than silently falling back to REST. Changes: - HybridTransport no longer catches gRPC errors and retries via REST - Removed fallbackOnError constructor parameter and field - Routing behavior preserved: unsupported endpoints → REST directly - gRPC-supported endpoints: errors propagate to caller - Simplified performRequest/performRequestAsync (no try/catch) - Updated tests: testGrpcErrorPropagatesForSupportedEndpoint Behavior: client.bulk(req) → gRPC (errors propagate if gRPC fails) client.search(req) → REST (not supported by gRPC, routed directly) Signed-off-by: Dayana Jean <jeadayao@amazon.com>
Stale references to 'automatic REST fallback' replaced with accurate 'REST routing for unsupported endpoints' language throughout. - GrpcTransport: updated javadoc and error message - GrpcDemo: rewrote Demo 3 to show REST routing (not fallback on error) - GrpcAwsSigV4: updated to use AwsGrpcTransport.awsBuilder() - GrpcBulkIT: renamed testRestFallback → testRestRouting Signed-off-by: Dayana Jean <jeadayao@amazon.com>
Per maintainer feedback: OpenSearchJavaClientTestCase and TestcontainersThreadFilter are internal test classes not exposed for external module use. Changes: - AbstractGrpcIT: now extends nothing, uses standard JUnit 4 + Assume - Removed dependency on OpenSearchJavaClientTestCase - Removed @ThreadLeakFilters(TestcontainersThreadFilter) - Uses Assume.assumeTrue() with manual version parsing - Reads cluster config from system properties directly - GrpcTransportSupport: converted from interface (extending OpenSearchTransportSupport) to utility class - GrpcBulkIT: no longer implements GrpcTransportSupport interface Signed-off-by: Dayana Jean <jeadayao@amazon.com>
Per maintainer feedback: opensearch-java baseline is JDK 8 and gRPC-Java supports Java 8. No technical reason to require JDK 11. Changes: - build.gradle.kts: targetCompatibility/sourceCompatibility → 1.8 - GrpcSigV4Test: replaced 'var' (Java 10+) with explicit types Signed-off-by: Dayana Jean <jeadayao@amazon.com>
Per maintainer feedback: opensearch-java has a hard dependency on Jackson 3.x, so it comes transitively. No need to declare it again. Signed-off-by: Dayana Jean <jeadayao@amazon.com>
Per maintainer feedback: integration tests were not being compiled or run. Added the standard java21 source set configuration used by java-client to java-client-grpc. Changes: - Added unitTest/integrationTest task definitions - Added java21 source set (src/test/java11) gated on JDK 21+ - Added test framework, testcontainers, opensearch-testcontainers deps - Added static import for JUnit Assert in GrpcBulkIT - Integration tests now compile and will run with: ./gradlew :java-client-grpc:integrationTest -Dtests.opensearch.version=3.5.0 Signed-off-by: Dayana Jean <jeadayao@amazon.com>
Adds the first gRPC-capable version to the test matrix so the gRPC integration tests run in CI. Includes both Java 21 and Java 25. Signed-off-by: Dayana Jean <jeadayao@amazon.com>
Spotless rejects wildcard imports. Replaced 'import static org.junit.Assert.*' with explicit imports for assertEquals, assertFalse, assertNotNull, assertTrue. Signed-off-by: Dayana Jean <jeadayao@amazon.com>
The java21 source set only contains integration tests (integTest package). Adding it to unitTest causes 'No tests found' failure since the filter excludes integTest classes. Only integrationTest needs the java21 classes. Signed-off-by: Dayana Jean <jeadayao@amazon.com>
- GrpcDemo.java: replaced custom header with standard Apache-2.0 license - GrpcAwsSigV4.java: fixed import ordering (AwsGrpcTransport alphabetical) - Removed unused imports Signed-off-by: Dayana Jean <jeadayao@amazon.com>
assumeGrpcSupported() now verifies both: 1. Server version is 3.5.0+ (via REST info endpoint) 2. gRPC port is actually reachable (TCP socket check) This prevents test failures when running integrationTest against OpenSearch versions that don't have gRPC enabled or when the gRPC port isn't exposed by testcontainers. Signed-off-by: Dayana Jean <jeadayao@amazon.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This PR adds a transparent gRPC support to the opensearch-java as a separate
java-client-grpcmodule with a translation layer, transport layers, connection management, and security implementation for gRPC such as TLS/basic auth, SigV4, and JWT. Bulk operations are automatically routed over gRPC for improved performance; lower latency, higher throughput, and smaller payloads via HTTP/2 and Protocol Buffers, while all other operations fall back to REST seamlessly. Users configure the transport once and use the standardOpenSearchClientAPI without any protobuf imports, channel management, or code changes.OpenSearch 3.5+ exposes a gRPC endpoint (default port 9400) alongside REST for Bulk and k-NN operations. This implementation bridges the gap so that existing client code benefits from gRPC performance without migration effort.
The gRPC transport lives in its own module to isolate gRPC dependencies (
grpc-netty-shaded,protobuf-java) from the core client, preventing classpath conflicts with the OpenSearch test framework.Users add the gRPC module as an optional dependency:
How It Works
The
HybridTransportwraps both aGrpcTransport(for bulk) and a standard REST transport (for everything else). Whenclient.bulk()is called, the request is converted from the client's Java types to protobuf, sent over gRPC, and the response is converted back — all transparently. If gRPC is unavailable or the conversion fails, the request automatically retries via REST.Authentication
All three authentication methods supported by OpenSearch are implemented as gRPC
ClientInterceptors that attach credentials to every outgoing call's metadata.TLS + Basic Auth:
AWS SigV4 signs each gRPC call using AWS SDK v2 credential providers. The interceptor constructs a synthetic URL from the gRPC method path, signs it with
AwsV4HttpSigner, and attaches the Authorization headers as gRPC metadata. Body-aware payload signing is supported for full SigV4 compliance.JWT uses a token supplier called on every request for automatic token rotation:
.jwtAuth(() -> myOidcProvider.getAccessToken())Connection Management
The gRPC
ManagedChannelprovides built-in connection health management that's more capable than REST's passive dead-node tracking. The channel automatically reconnects on failure with exponential backoff, and theGrpcChannelHealthMonitorexposes the connectivity state machine (IDLE → CONNECTING → READY → TRANSIENT_FAILURE) so callers can check readiness or register state change callbacks.Retry logic is configurable via
GrpcTransportOptions— max retries, backoff interval, keepalive pings, idle timeout, and max inbound message size all have sensible defaults that match the OpenSearch server's gRPC settings.Translation Layer
BulkRequestConverterwalks the typedBulkOperationlist, serializes document bodies to JSON bytes viaJsonpMapper, and builds the protobufBulkRequest.BulkResponseConverterconverts each protobufResponseItemback to the client'sBulkResponseItemwith all fields. Status code mapping follows the OpenSearch server'sRestToGrpcStatusConverter.Tests
The implementation includes 112 unit tests across 6 test files covering all conversion logic, transport routing, authentication interceptors, channel management, and TLS configuration. Three condensed integration tests validate end-to-end behavior against a real OpenSearch 3.5+ cluster using the project's existing test framework (
OpenSearchJavaClientTestCase+ Testcontainers). Tests are version-gated viaassumeTrueand skip automatically on older clusters.CI Configuration
The Docker configuration in
.ci/opensearch/enables gRPC transport (port 9400) in the test container. A standalonevalidate-grpc-integration.shscript is included for local validation. gRPC integration tests run via./gradlew :java-client-grpc:test.Dependencies
gRPC support is configured as an optional feature (
grpcSupport) with zero impact on users who don't enable it. Dependencies areio.grpc(1.68.0),com.google.protobuf(3.25.5), andorg.opensearch:protobufs(1.2.0).Related
This is the Java counterpart to the opensearch-py gRPC implementation, following the same design pattern:
OpenSearch gRPC API documentation: https://docs.opensearch.org/latest/api-reference/grpc-apis/index/
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
For more information on following Developer Certificate of Origin and signing off your commits, please check here.