Skip to content

M31 · gRPC engine: generated stubs, channel and auth - #54

Merged
tonytonycoder11 merged 1 commit into
mainfrom
feat/m31-grpc-engine
Jul 31, 2026
Merged

M31 · gRPC engine: generated stubs, channel and auth#54
tonytonycoder11 merged 1 commit into
mainfrom
feat/m31-grpc-engine

Conversation

@tonytonycoder11

Copy link
Copy Markdown
Contributor

First slice of #52. The foundation of kdrant-transport-grpc, not the transport itself — see the scope
note at the bottom.

The decision this PR is really about

The engine generates its own stubs from Qdrant's .proto files rather than depending on
io.qdrant:client. Two reasons, both about what the module costs its users:

  • grpc-kotlin emits suspend functions and Flows, which is the shape QdrantTransport already
    has. Wrapping the official client would mean adapting ListenableFuture back into coroutines — the
    exact conversion the migration guide tells people not to
    write by hand.
  • Generating decides the dependency set instead of inheriting it. This module resolves
    grpc-okhttp; the shaded Netty jar the official client carries is around 9 MB on its own, most of
    what the README's footprint table charges to it. An opt-in gRPC engine that quietly costs what gRPC
    usually costs would make the opt-in pointless.

Verified

  • Codegen works on Gradle 9.6.1 / Kotlin 2.4.10, which was the real unknown: protobuf-gradle-plugin
    0.10.0 with protoc 4.35.1, grpc-java 1.83.1 and grpc-kotlin 1.5.0 produce 265 Kotlin and 12 Java
    sources, including coroutine stubs for Collections, Points, Snapshots and Health. The module
    compiles under explicitApi().
  • Half the exit criterion already holds: :kdrant-transport-rest:dependencies --configuration runtimeClasspath resolves zero gRPC or protobuf entries.
  • The api-key test runs a real exchange over gRPC's in-process transport and asserts the metadata the
    server received, not the interceptor's own bookkeeping.

Choices worth reviewing

  • The protos are vendored verbatim at v1.18.2, the version the contract tests and the CI matrix
    already pin. Refreshing is a re-download, never a patch — a vendored file that has been edited is one
    nobody can diff against upstream.
  • qdrant.proto is deliberately not vendored. Its only unique call returns the server's title,
    version and commit, which no QdrantTransport operation needs, and its imports pull in six internal
    cluster services to get it. The probes go through the standard health_check.proto instead.
  • Binary-compatibility validation ignores the generated packages (qdrant, grpc.health.v1). Their
    surface is Qdrant's to change, not ours to promise, and tracking it would bury the module's real API
    under thousands of generated lines. The .api file is currently empty, which is correct: nothing
    hand-written is public yet.
  • protoc had to be renamed to protobuf-protoc in the catalog. A library whose name is the prefix of
    another (protoc-gen-grpc-java) becomes a namespace and stops being reachable as a leaf.

Scope

No QdrantTransport implementation and no CHANGELOG entry. The seam has around 45 operations and
they are the bulk of M31's estimate; a partial implementation cannot compile without stubbing the rest
with TODO(), and that is not something to merge into main. Nothing user-facing has changed yet,
which is why the changelog stays quiet until the transport lands.

…ient

The engine could have wrapped io.qdrant:client and been done in an afternoon.
It generates its own stubs from Qdrant's .proto files instead, for two reasons
that are both about what the module costs the people who use it.

grpc-kotlin emits suspend functions and Flows, which is the shape QdrantTransport
already has. Wrapping the official client would mean adapting ListenableFuture
back into coroutines, which is the exact conversion the migration guide tells
people not to write by hand.

Generating also decides the dependency set rather than inheriting it. The engine
resolves grpc-okhttp; the shaded Netty jar the official client carries is around
nine megabytes on its own, most of what the README's footprint table charges to
it. An opt-in gRPC engine that quietly costs what gRPC usually costs would have
made the opt-in pointless.

The protos are vendored verbatim at v1.18.2, the version the contract tests and
the CI matrix already pin, so moving forward is a re-download and never a patch.
qdrant.proto is left out: its only unique call returns the server's version,
which no transport operation needs, and its imports drag in six internal cluster
services to get it.

Binary-compatibility validation ignores the generated packages. Their surface is
Qdrant's to change, not ours to promise, and tracking it would bury the module's
real API under thousands of generated lines.

The transport itself is not here. What is here is the channel, the api-key
metadata and a test that asserts what a real server received over the in-process
transport, plus the proof that a REST-only build still resolves zero gRPC and
zero protobuf.
@tonytonycoder11
tonytonycoder11 requested a review from a team as a code owner July 31, 2026 10:04
@tonytonycoder11
tonytonycoder11 merged commit 3963582 into main Jul 31, 2026
6 checks passed
@tonytonycoder11
tonytonycoder11 deleted the feat/m31-grpc-engine branch July 31, 2026 10:36
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