Skip to content

Commit 86d480a

Browse files
committed
[GRPC] Add guide for "Contributing to gRPC"
Signed-off-by: Karen X <karenxyr@gmail.com>
1 parent 672039d commit 86d480a

File tree

2 files changed

+273
-11
lines changed

2 files changed

+273
-11
lines changed

modules/transport-grpc/README.md

Lines changed: 237 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,235 @@ The `transport-grpc` module initializes a new client/server transport implementi
55

66
**Note:** As a module, transport-grpc is included by default with all OpenSearch installations. However, it remains opt-in and must be explicitly enabled via configuration settings.
77

8-
## GRPC Settings
8+
## Table of Contents
9+
10+
- [transport-grpc](#transport-grpc)
11+
- [Table of Contents](#table-of-contents)
12+
- [Contributing to gRPC APIs](#contributing-to-grpc-apis)
13+
- [Overview](#overview)
14+
- [Workflow](#workflow)
15+
- [Step-by-Step Guide](#step-by-step-guide)
16+
- [Step 0: Submit Fixes to Related Repositories (If Needed)](#step-0-submit-fixes-to-related-repositories-if-needed)
17+
- [Step 1: Generate Protobuf Definitions from OpenAPI Spec](#step-1-generate-protobuf-definitions-from-openapi-spec)
18+
- [Step 2: Generate and Package Local Protobuf JAR](#step-2-generate-and-package-local-protobuf-jar)
19+
- [Step 3: Set Up OpenSearch Repository with Local Protobuf JAR](#step-3-set-up-opensearch-repository-with-local-protobuf-jar)
20+
- [Step 4: Implement Your Core Contribution](#step-4-implement-your-core-contribution)
21+
- [A. Adding a Core Query Converter](#a-adding-a-core-query-converter)
22+
- [B. Extending a gRPC Service](#b-extending-a-grpc-service)
23+
- [C. Building a Custom Core Interceptor](#c-building-a-custom-core-interceptor)
24+
- [Step 5: Test Your Implementation](#step-5-test-your-implementation)
25+
- [Step 6: Submit Pull Requests](#step-6-submit-pull-requests)
26+
- [Merge Order Summary](#merge-order-summary)
27+
- [Development Guide](#development-guide)
28+
- [GRPC Settings](#grpc-settings)
29+
- [Other gRPC Settings](#other-grpc-settings)
30+
- [Notes:](#notes)
31+
- [Example configurations:](#example-configurations)
32+
- [Thread Pool Monitoring](#thread-pool-monitoring)
33+
- [Testing](#testing)
34+
- [Unit Tests](#unit-tests)
35+
- [Integration Tests](#integration-tests)
36+
- [Running OpenSearch with gRPC Enabled](#running-opensearch-with-grpc-enabled)
37+
38+
## Contributing to gRPC APIs
39+
40+
This section is for contributors who want to add new gRPC functionality directly to OpenSearch core (not as an external plugin). This includes adding new query converters, extending gRPC services, or building custom interceptors that will be part of the core distribution.
41+
42+
### Overview
43+
44+
Contributing to core gRPC may involve working with up to four repositories:
45+
1. **opensearch-api-specification**: Fix API spec errors (if any are found)
46+
2. **opensearch-protobufs**: Generate protobuf schemas from the API spec
47+
3. **OpenSearch**: Implement Java code that uses the protobufs (query converters, services, interceptors)
48+
4. **documentation-website**: Update public documentation for your gRPC APIs
49+
50+
**Note:** If you're only building interceptors (without protobuf changes), you can skip Steps 1-2 and start directly at Step 3.
51+
52+
### Workflow
53+
54+
```
55+
┌─────────────────────────────────────────────────────────────┐
56+
│ 1. opensearch-protobufs: Define/modify .proto files │
57+
│ - Add new message types │
58+
│ - Add new service endpoints │
59+
│ - Generate local protobuf JAR │
60+
└─────────────────────────────────────────────────────────────┘
61+
62+
┌─────────────────────────────────────────────────────────────┐
63+
│ 2. OpenSearch: Implement Java code │
64+
│ - Import local protobuf JAR (if protos changed) │
65+
│ - Implement query converters / services / interceptors │
66+
│ - Test your implementation │
67+
└─────────────────────────────────────────────────────────────┘
68+
69+
┌─────────────────────────────────────────────────────────────┐
70+
│ 3. Submit PRs (coordinated merge) │
71+
│ - PR to opensearch-protobufs (merged first) │
72+
│ - PR to OpenSearch (update version, then merge) │
73+
│ - PR to documentation-website (can merge independently) │
74+
└─────────────────────────────────────────────────────────────┘
75+
```
76+
77+
### Step-by-Step Guide
78+
79+
#### Step 0: Submit Fixes to Related Repositories (If Needed)
80+
81+
**Before generating protobufs**, if you discover errors while working with the API:
82+
83+
- **API Specification fixes:** If you find errors in the OpenSearch API spec, submit a PR to [opensearch-api-specification](https://github.com/opensearch-project/opensearch-api-specification). After the spec fix is merged, regenerate protobufs to incorporate the corrections.
84+
- **Documentation fixes:** If you find errors in public documentation, submit a PR to [documentation-website](https://github.com/opensearch-project/documentation-website)
85+
- **Remember:** The server code (`toXContent`/`fromXContent` methods for REST APIs) is the source of truth. If there's a discrepancy between the API spec and server code, the server is correct.
86+
87+
#### Step 1: Generate Protobuf Definitions from OpenAPI Spec
88+
89+
**Skip this step if you're only building interceptors without protobuf changes.**
90+
91+
Clone the opensearch-protobufs repository and follow the [Protobuf Local Convert Guide](https://github.com/opensearch-project/opensearch-protobufs/blob/main/DEVELOPER_GUIDE.md#protobuf-local-convert-guide) to generate protobufs from the OpenSearch API specification.
92+
93+
```bash
94+
git clone https://github.com/opensearch-project/opensearch-protobufs.git
95+
cd opensearch-protobufs
96+
```
97+
98+
#### Step 2: Generate and Package Local Protobuf JAR
99+
100+
**Skip this step if you're only building interceptors without protobuf changes.**
101+
102+
**Follow the complete guide:** [Generate Java Code and Packaging as a Maven/Gradle Dependency](https://github.com/opensearch-project/opensearch-protobufs/blob/main/DEVELOPER_GUIDE.md#generate-java-code-and-packaging-as-a-mavengradle-dependency)
103+
104+
**Summary:**
105+
1. Build the Java protobuf code with Bazel
106+
2. Run `./tools/java/package_proto_jar.sh` to create and install the JAR to your local Maven repository
107+
3. Note the version from `version.properties` (e.g., `1.1.0-SNAPSHOT`)
108+
109+
The JAR will be installed to `~/.m2/repository/org/opensearch/protobufs/opensearch-protobufs/`
110+
111+
#### Step 3: Set Up OpenSearch Repository with Local Protobuf JAR
112+
113+
1. **Clone OpenSearch repository (if not already cloned):**
114+
```bash
115+
git clone https://github.com/opensearch-project/OpenSearch.git
116+
cd OpenSearch
117+
```
118+
119+
2. **Configure to use local protobuf JAR (if you made protobuf changes):**
120+
121+
Edit `build.gradle` in the OpenSearch root:
122+
```groovy
123+
allprojects {
124+
repositories {
125+
mavenLocal() // Add this to use your local Maven repository
126+
// ... other repositories ...
127+
}
128+
}
129+
```
130+
131+
Then update the version in `gradle/libs.versions.toml`:
132+
```toml
133+
opensearchprotobufs = "1.1.0-SNAPSHOT"
134+
```
135+
136+
3. **Verify the setup:**
137+
```bash
138+
./gradlew :modules:transport-grpc:build
139+
```
140+
141+
#### Step 4: Implement Your Core Contribution
142+
143+
Now you can implement your gRPC functionality in the OpenSearch codebase. Choose the appropriate section based on what you're building.
144+
145+
##### A. Adding a Core Query Converter
146+
147+
**Requires protobuf changes (Steps 1-2).**
148+
149+
Query converters transform protobuf query messages into OpenSearch QueryBuilder objects.
150+
151+
**Implementation details:** See [SPI documentation](spi/README.md#querybuilderprotoconverter) for complete examples.
152+
153+
##### B. Extending a gRPC Service
154+
155+
**Requires protobuf changes (Steps 1-2).**
156+
157+
gRPC services expose new API endpoints for client applications.
158+
159+
**Implementation details:** See [SPI documentation](spi/README.md#grpcservicefactory) for complete examples.
160+
161+
##### C. Building a Custom Core Interceptor
162+
163+
**Does NOT require protobuf changes - you can skip Steps 1-2 and start here!**
164+
165+
Interceptors process all incoming gRPC requests for cross-cutting concerns like authentication, logging, and metrics.
166+
167+
**Implementation details:** See [SPI documentation](spi/README.md#grpc-interceptors) for complete examples.
168+
169+
#### Step 5: Test Your Implementation
170+
171+
See the [Testing](#testing) section in the Development Guide below for complete instructions on:
172+
- Running unit tests
173+
- Running integration tests
174+
- Manual testing with OpenSearch
175+
176+
#### Step 6: Submit Pull Requests
177+
178+
**Important: PRs must be coordinated and merged in a specific order.**
179+
180+
1. **Submit PR to opensearch-protobufs (if you made protobuf changes):**
181+
- Title: "Add protobuf definitions for [feature name]"
182+
- Include:
183+
- New/modified `.proto` files
184+
- Updated documentation
185+
- Reasoning for the changes
186+
- Link to the corresponding OpenSearch PR
187+
- **This PR must be merged FIRST**
188+
189+
2. **After protobufs PR is merged, update OpenSearch:**
190+
- Update the protobuf version in `gradle/libs.versions.toml`:
191+
```toml
192+
opensearchprotobufs = "1.1.0" # Use the newly published version
193+
```
194+
- Remove `mavenLocal()` from `build.gradle` if you added it
195+
196+
3. **Submit PR to OpenSearch:**
197+
- Title: "Add gRPC support for [feature name]"
198+
- Include:
199+
- Implementation code (converters/services/interceptors)
200+
- Unit/integration tests
201+
- Updated `gradle/libs.versions.toml` (if protobuf version changed)
202+
- Reference the opensearch-protobufs PR in the description
203+
- **This PR can be merged AFTER the protobufs PR is merged and the version is updated**
204+
205+
4. **Submit PR to documentation-website:**
206+
- Update the gRPC API documentation with your new features
207+
- Example: [PR #11614 - gRPC Documentation for 3.4](https://github.com/opensearch-project/documentation-website/pull/11614)
208+
- Include:
209+
- API reference updates
210+
- Usage examples
211+
- Any new configuration options
212+
- **This PR can be merged independently** but should ideally be coordinated with the OpenSearch release
213+
214+
### Merge Order Summary
215+
216+
```
217+
0. (If needed) opensearch-api-specification PR → MERGE FIRST (if API spec fixes are required)
218+
↓ Regenerate protobufs after spec fix is merged
219+
220+
1. opensearch-protobufs PR → MERGE FIRST
221+
222+
2. Protobufs published to Maven Central
223+
224+
3. Update OpenSearch gradle/libs.versions.toml with new version
225+
226+
4. OpenSearch PR → MERGE SECOND
227+
228+
5. documentation-website PR → MERGE (can be independent)
229+
```
230+
231+
---
232+
233+
## Development Guide
234+
235+
### GRPC Settings
236+
9237
Enable this transport with:
10238
11239
```
@@ -20,8 +248,7 @@ setting 'aux.transport.types', '[secure-tra
20248
setting 'aux.transport.secure-transport-grpc.port', '9400-9500' //optional
21249
```
22250
23-
24-
### Other gRPC Settings
251+
#### Other gRPC Settings
25252
26253
| Setting Name | Description | Example Value | Default Value |
27254
|-------------------------------------------------|----------------------------------------------------------------------------------------------------------------|-----------------------|----------------------|
@@ -39,12 +266,12 @@ setting 'aux.transport.secure-transport-grpc.port', '9400-9500' //optional
39266
40267
---
41268
42-
### Notes:
269+
#### Notes:
43270
- For duration-based settings (e.g., `max_connection_age`), you can use units such as `ms` (milliseconds), `s` (seconds), `m` (minutes), etc.
44271
- For size-based settings (e.g., `max_msg_size`), you can use units such as `b` (bytes), `kb`, `mb`, `gb`, etc.
45272
- All settings are node-scoped unless otherwise specified.
46273
47-
### Example configurations:
274+
#### Example configurations:
48275
```
49276
setting 'grpc.publish_port', '9400'
50277
setting 'grpc.host', '["0.0.0.0"]'
@@ -59,7 +286,7 @@ setting 'grpc.netty.max_msg_size', '10mb'
59286
setting 'grpc.netty.keepalive_timeout', '1s'
60287
```
61288
62-
## Thread Pool Monitoring
289+
### Thread Pool Monitoring
63290
64291
The dedicated thread pool used for gRPC request processing is registered as a standard OpenSearch thread pool named `grpc`, controlled by the `grpc.netty.executor_count` setting.
65292
@@ -69,21 +296,21 @@ The gRPC thread pool stats can be monitored using:
69296
curl -X GET "localhost:9200/_nodes/stats/thread_pool?filter_path=nodes.*.thread_pool.grpc"
70297
```
71298

72-
## Testing
299+
### Testing
73300

74-
### Unit Tests
301+
#### Unit Tests
75302

76303
```bash
77304
./gradlew :modules:transport-grpc:test
78305
```
79306

80-
### Integration Tests
307+
#### Integration Tests
81308

82309
```bash
83310
./gradlew :modules:transport-grpc:internalClusterTest
84311
```
85312

86-
### Running OpenSearch with gRPC Enabled
313+
#### Running OpenSearch with gRPC Enabled
87314

88315
To run OpenSearch with the gRPC transport enabled:
89316

modules/transport-grpc/spi/README.md

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,37 @@
22

33
Service Provider Interface (SPI) for the OpenSearch gRPC transport module. This module provides interfaces and utilities that allow external plugins to extend the gRPC transport functionality.
44

5+
## Table of Contents
6+
7+
- [transport-grpc-spi](#transport-grpc-spi)
8+
- [Table of Contents](#table-of-contents)
9+
- [Overview](#overview)
10+
- [Key Components](#key-components)
11+
- [QueryBuilderProtoConverter](#querybuilderprotoconverter)
12+
- [QueryBuilderProtoConverterRegistry](#querybuilderprotoconverterregistry)
13+
- [GrpcInterceptorProvider](#grpcinterceptorprovider)
14+
- [GrpcServiceFactory](#grpcservicefactory)
15+
- [Usage for Plugin Developers](#usage-for-plugin-developers)
16+
- [1. Add Dependency](#1-add-dependency)
17+
- [2. Declare Extension in build.gradle](#2-declare-extension-in-buildgradle)
18+
- [3. Create SPI Registration File(s)](#3-create-spi-registration-files)
19+
- [QueryBuilderProtoConverter](#querybuilderprotoconverter-1)
20+
- [1. Implement Custom Query Converter](#1-implement-custom-query-converter)
21+
- [2. Register Your Converter](#2-register-your-converter)
22+
- [3. Accessing the Registry (For Complex Queries)](#3-accessing-the-registry-for-complex-queries)
23+
- [Testing](#testing)
24+
- [Unit Tests](#unit-tests)
25+
- [4. Testing Your Custom Converter](#4-testing-your-custom-converter)
26+
- [Real-World Example: k-NN Plugin](#real-world-example-k-nn-plugin)
27+
- [gRPC Interceptors](#grpc-interceptors)
28+
- [Overview](#overview-1)
29+
- [Basic Usage](#basic-usage)
30+
- [Understanding Interceptor Ordering](#understanding-interceptor-ordering)
31+
- [How Order Values Work](#how-order-values-work)
32+
- [Duplicate Order Values](#duplicate-order-values)
33+
- [GrpcServiceFactory](#grpcservicefactory-1)
34+
- [1. Implement Custom Service Factory](#1-implement-custom-service-factory)
35+
536
## Overview
637

738
The `transport-grpc-spi` module enables plugin developers to:
@@ -11,6 +42,10 @@ The `transport-grpc-spi` module enables plugin developers to:
1142
- Register gRPC interceptors with explicit ordering
1243
- Register `BindableService` implementation to the gRPC transport
1344

45+
**For contributing to OpenSearch gRPC APIs, see the [Contributing to gRPC APIs](../README.md#contributing-to-grpc-apis) guide in the transport-grpc module.**
46+
47+
---
48+
1449
## Key Components
1550

1651
### QueryBuilderProtoConverter
@@ -400,7 +435,7 @@ Each interceptor must have a unique order value.
400435

401436
## GrpcServiceFactory
402437

403-
### 1. Implement Custom Query Converter
438+
### 1. Implement Custom Service Factory
404439

405440
Several node resources are exposed to a `GrpcServiceFactory` for use within services such as client, settings, and thread pools.
406441
A plugin's `GrpcServiceFactory` implementation will be discovered through the SPI registration file and registered on the gRPC transport.

0 commit comments

Comments
 (0)