Skip to content

[GRPC] Add DocumentService and Bulk GRPC endpoint v1#17727

Merged
andrross merged 8 commits intoopensearch-project:mainfrom
karenyrx:bulk_grpc_2
Apr 4, 2025
Merged

[GRPC] Add DocumentService and Bulk GRPC endpoint v1#17727
andrross merged 8 commits intoopensearch-project:mainfrom
karenyrx:bulk_grpc_2

Conversation

@karenyrx
Copy link
Copy Markdown
Contributor

@karenyrx karenyrx commented Mar 30, 2025

Description

Implement DocumentService GRPC service, starting with the Bulk endpoint.

The goal is to maintain parity with the HTTP APIs.

The overall flow of how this works is:

  1. The protobuf definitions are based off the OpenSearch API spec (the source of truth). (In the future, they will be auto-generated whenever the spec change.)
  2. The compiled and generated protobuf Java code is published to the Sonatype Maven repo.
  3. The protobuf jars are imported to Core repo as a Gradle dependency.
  4. The Core implementation is done by tracing through the Bulk REST API implementation. It adds a correspondingly named utility class as the original class in the plugins/transport-grpc folder, with the suffix *ProtoUtils. Javadocs are added above each proto conversion method to easily reference the original REST method. The methods follow the HTTP side closely.

Test Plan

  1. Start local grpc server
export JAVA_HOME=/opt/jvm/jdk-21
export PATH=$JAVA_HOME/bin:$PATH
which java

./gradlew run -PinstalledPlugins="['transport-grpc']" --info -Dtests.opensearch.aux.transport.types="[experimental-transport-grpc]" -Drepos.mavenLocal
  1. Copy the raw protobufs to a local folder, and change path in below sample request accordingly:
grpcurl -import-path ~/opensearch/opensearch-protobufs -d @ -proto ~/opensearch/opensearch-protobufs/document_service.proto -plaintext localhost:9400 org.opensearch.protobufs.services.DocumentService/Bulk < bulk_grpc.json
{// payload}

Test 1: Testing by Passing all possible Request parameter fields

{
  "index": "my_index",
  "source": {
    "bool_value": true,
    "string_array": []
  },
  "source_excludes": [
    "field1",
    "field2"
  ],
  "source_includes": [
    "field3",
    "field4"
  ],
  "pipeline": "my_ingest_pipeline",
  "refresh": "REFRESH_TRUE",
  "require_alias": false,
  "routing": "1",
  "timeout": "1m",
  "type": "_doc",
  "wait_for_active_shards": {
    "int32_value": 1
  },
  "source_type": "SOURCE_TYPE_UNSPECIFIED",
  "request_body":[
    {
      "index":{
        "id":"2",
        "index":"my_index",
        "require_alias": false,
        "routing": "0",
        "pipeline" : "my_ingest_pipeline",
        "op_type" : "OP_TYPE_UNSPECIFIED",
        "version_type": "VERSION_TYPE_UNSPECIFIED"
      },
      "doc":"eyJ0aXRsZSI6Ik9wZW5TZWFyY2ggQmFzaWNzIn0=",
      "source": {
        "fetch" : true
      }
    },
    {
      "create":{
        "id":"1",
        "index":"my_index",
        "require_alias": false,
        "pipeline" : "my_ingest_pipeline",
        "routing": "1"
      },
      "doc":"eyJ0aXRsZSI6Ik9wZW5TZWFyY2ggQmFzaWNzIn0=",
      "source": {
        "fetch" : true
      }
    },
    {
      "update": {
        "id": "2",
        "index": "my_index",
        "routing": "0",
        "require_alias": false,
        "if_primary_term": 1,
        "if_seq_no":0
      },
      "doc": "eyJrZXkxIjoidmFsdWUyIn0K"
    },
    {
      "delete": {
        "id": "2",
        "index": "my_index",
        "routing": "0",
        "if_primary_term": 1,
        "if_seq_no": 1
      }
    }
  ]
}

Example successful response:

  "bulkResponseBody": {
    "errors": false,
    "items": [
      {
        "index": {
          "id": {
            "string": "2"
          },
          "index": "my_index",
          "status": 201,
          "primaryTerm": "1",
          "result": "created",
          "seqNo": "0",
          "shards": {
            "successful": 1,
            "total": 2
          },
          "version": "1",
          "forcedRefresh": true
        }
      },
      {
        "create": {
          "id": {
            "string": "1"
          },
          "index": "my_index",
          "status": 201,
          "primaryTerm": "1",
          "result": "created",
          "seqNo": "0",
          "shards": {
            "successful": 1,
            "total": 2
          },
          "version": "1",
          "forcedRefresh": true
        }
      },
      {
        "update": {
          "id": {
            "string": "2"
          },
          "index": "my_index",
          "status": 200,
          "primaryTerm": "1",
          "result": "updated",
          "seqNo": "1",
          "shards": {
            "successful": 1,
            "total": 2
          },
          "version": "2",
          "forcedRefresh": true,
          "get": {
            "found": true,
            "seqNo": "1",
            "primaryTerm": "1",
            "source": "e30="
          }
        }
      },
      {
        "delete": {
          "id": {
            "string": "2"
          },
          "index": "my_index",
          "status": 200,
          "primaryTerm": "1",
          "result": "deleted",
          "seqNo": "2",
          "shards": {
            "successful": 1,
            "total": 2
          },
          "version": "3",
          "forcedRefresh": true
        }
      }
    ],
    "took": "87",
    "ingestTook": "0"
  }
}

Verified parity with the HTTP response:

{"took":76,"ingest_took":0,"errors":false,"items":[{"index":{"_index":"my_index","_id":"2","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1,"status":201}},{"create":{"_index":"my_index","_id":"1","_version":1,"result":"created","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":0,"_primary_term":1,"status":201}},{"update":{"_index":"my_index","_id":"2","_version":2,"result":"updated","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":1,"_primary_term":1,"get":{"_seq_no":1,"_primary_term":1,"found":true,"_source":{}},"status":200}},{"delete":{"_index":"my_index","_id":"2","_version":3,"result":"deleted","_shards":{"total":2,"successful":1,"failed":0},"_seq_no":2,"_primary_term":1,"status":200}}]}

Example error response (submitting the same "create" operation twice):

{
  "bulkResponseBody": {
    "errors": true,
    "items": [
      {
        "create": {
          "id": {
            "string": "3"
          },
          "index": "my_index1",
          "status": 409,
          "error": {
            "type": "version_conflict_engine_exception",
            "reason": "[3]: version conflict, document already exists (current version [1])",
            "stackTrace": "[my_index1/TxTenbTvQyySzhcM-vzrLg][[my_index1][0]] VersionConflictEngineException[[3]: version conflict, document already exists (current version [1])]\n"
          }
        }
      }
    ],
    "took": "2"
  }
}

Future work

  1. Write an integration test for bulk request submitted E2E
  2. Offline/manual parity testing of the GRPC vs HTTP Bulk requests and responses
  3. Switch from using the SNAPSHOT jar to a jar from the central Maven repo
  4. Fixing the Bulk Spec (PR: Fix Bulk API schemas opensearch-api-specification#843)
  5. Converting HTTP status codes to GRPC ones in the response-side

Related Issues

#16784

Check List

  • Functionality includes testing.
  • API changes companion pull request created, if applicable.
  • Public documentation issue/PR created, if applicable.

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.

@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 21dac0c: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 6a341bd: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@karenyrx karenyrx changed the title [GRPC] DocumentService and Bulk GRPC endpoint v1 [GRPC] Add DocumentService and Bulk GRPC endpoint v1 Mar 30, 2025
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 1485676: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for d763e8d: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 772f42e: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@karenyrx karenyrx force-pushed the bulk_grpc_2 branch 3 times, most recently from 782097d to 8292a05 Compare March 31, 2025 21:08
@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 8292a05: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for 62453b1: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions
Copy link
Copy Markdown
Contributor

❌ Gradle check result for b3a261c: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Signed-off-by: Karen Xu <karenxyr@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 1, 2025

❌ Gradle check result for 5d83d26: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 3, 2025

❌ Gradle check result for e4faba2: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

karenyrx added 2 commits April 3, 2025 21:22
Signed-off-by: Karen Xu <karenxyr@gmail.com>
Signed-off-by: Karen X <karenxyr@gmail.com>
Copy link
Copy Markdown
Member

@andrross andrross left a comment

Choose a reason for hiding this comment

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

What's the deal with the bouncy castle license files that have been removed?

Comment thread libs/core/src/main/java/org/opensearch/OpenSearchException.java
Comment thread plugins/transport-grpc/build.gradle
Comment thread .gitignore Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 3, 2025

❕ Gradle check result for 09dd19d: UNSTABLE

Please review all flaky tests that succeeded after retry and create an issue if one does not already exist to track the flaky failure.

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 3, 2025

Codecov Report

Attention: Patch coverage is 87.77090% with 79 lines in your changes missing coverage. Please review.

Project coverage is 72.39%. Comparing base (5487374) to head (3417719).
Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...est/document/bulk/BulkRequestParserProtoUtils.java 79.06% 18 Missing and 18 partials ⚠️
...response/common/OpenSearchExceptionProtoUtils.java 80.72% 12 Missing and 4 partials ⚠️
...o/request/common/FetchSourceContextProtoUtils.java 83.72% 2 Missing and 5 partials ⚠️
...oto/response/document/get/GetResultProtoUtils.java 80.00% 4 Missing and 2 partials ⚠️
...onse/document/bulk/BulkItemResponseProtoUtils.java 85.71% 2 Missing and 3 partials ⚠️
...o/request/document/bulk/BulkRequestProtoUtils.java 86.36% 2 Missing and 1 partial ⚠️
...g/opensearch/plugin/transport/grpc/GrpcPlugin.java 80.00% 1 Missing and 1 partial ⚠️
...uest/document/bulk/ActiveShardCountProtoUtils.java 87.50% 2 Missing ⚠️
...rt/grpc/proto/request/common/ScriptProtoUtils.java 96.96% 0 Missing and 1 partial ⚠️
...ponse/document/common/DocumentFieldProtoUtils.java 50.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##               main   #17727    +/-   ##
==========================================
  Coverage     72.38%   72.39%            
- Complexity    66063    66264   +201     
==========================================
  Files          5358     5384    +26     
  Lines        306485   307127   +642     
  Branches      44402    44548   +146     
==========================================
+ Hits         221854   222344   +490     
- Misses        66435    66585   +150     
- Partials      18196    18198     +2     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Signed-off-by: Karen Xu <karenxyr@gmail.com>
@karenyrx
Copy link
Copy Markdown
Contributor Author

karenyrx commented Apr 4, 2025

What's the deal with the bouncy castle license files that have been removed?

can't seem to reproduce how i got it, but have removed it manually for now
(some combination of ./gradlew precommit + modifying build.gradle files in the test/framework/ directory + rebasing main?)

Signed-off-by: Karen Xu <karenxyr@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 4, 2025

❌ Gradle check result for 08e419e: FAILURE

Please examine the workflow log, locate, and copy-paste the failure(s) below, then iterate to green. Is the failure a flaky test unrelated to your change?

Signed-off-by: Karen Xu <karenxyr@gmail.com>
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 4, 2025

❕ Gradle check result for 3417719: UNSTABLE

Please review all flaky tests that succeeded after retry and create an issue if one does not already exist to track the flaky failure.

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.

4 participants