blob: b880520dcd31552cd49ea3f686d4f49f1c3e67ca [file] [view]
# EventMesh protocols and SDKs
> **Audience:** anyone choosing a wire protocol or SDK. The canonical
> inventory of protocols, server-side plugins, and client SDKs, with
> GA / Beta / Experimental / Legacy status (README table is authoritative).
---
This issue tracks the separation called out in #5296 review question Q5
(2026-09-07): the modern **HTTP + CloudEvents + EventMeshFrame** path must be
the only one downstream code depends on, while the legacy TCP, gRPC, and
OpenMessaging paths must be clearly marked and isolated from the modern SDK
public surface.
## 1. Wire protocols
| Protocol | Status | Wire format | Where it lives | Replacement |
| --- | --- | --- | --- | --- |
| CloudEvents 1.0 over HTTP | **GA** | CloudEvents JSON (binary-mode optional) | runtime ingress / egress (HTTP), `eventmesh-protocol-plugin/eventmesh-protocol-cloudevents` | - |
| EventMeshFrame (internal) | **GA** | `org.apache.eventmesh.common.wire.EventMeshFrame` (Frame architecture) | runtime internal; producer / storage / push path | - |
| A2A (Agent-to-Agent) | **Experimental** | A2A JSON-RPC + SSE | `eventmesh-protocol-plugin/eventmesh-protocol-a2a`, A2A gateway on Runtime | - |
| MeshMessage TCP | **Legacy** | length-prefixed `MeshMessage` bytes | runtime `tcp/` subpackage, `eventmesh-protocol-plugin/eventmesh-protocol-meshmessage/resolver/tcp` | CloudEvents HTTP, or A2A (for agent workloads) |
| gRPC (CloudEvents + EventMeshMessage) | **Beta** | protobuf over HTTP/2 | runtime `grpc/` bridge (issue #5411), `eventmesh-protocol-plugin/eventmesh-protocol-meshmessage/resolver/grpc` | CloudEvents HTTP for new clients |
| OpenMessaging API (TCP) | **Legacy** | OMA spec, used by the legacy TCP client only | `eventmesh-sdks/eventmesh-sdk-java/client/tcp/impl/openmessage` | CloudEvents HTTP client |
> **GA** = production-ready and the recommended path. **Beta** = stable but
> the API surface may still shift. **Experimental** = subject to breaking
> change without notice. **Legacy** = still works, but is no longer the
> recommended choice and is being phased out.
### 1.1 Legacy gRPC bridge (served, opt-in — issue #5411)
The v2 runtime serves the legacy SDK gRPC protocol as a **compatibility
bridge** on `eventmesh.grpc.port` (1.x default `10205`; unset / `-1` =
disabled, opt-in like the WS port). There is no second messaging engine:
every call maps onto the same v2 ingress/delivery pipeline the HTTP plane
uses (WAL durability, at-least-once, shared retry/DLQ).
| Legacy call | v2 mapping |
| --- | --- |
| `publish` / `batchPublish` / `publishOneWay` / `batchPublishOneWay` | proto `CloudEvent` v2 CloudEvent, persisted via `UniIngressService.publish` (topic = proto `subject` attribute) |
| `requestReply` | v2 request/reply correlation (`UniIngressService.request`), TTL attribute drives the timeout |
| `subscribe` (webhook `url`) | `WebHookChannel` push target + v2 subscription per topic |
| `subscribeStream` (bidi) | `GrpcStreamChannel` push target pumping the v2 dispatcher into the stream; ACKs ride back as stream replies |
| `unsubscribe` | v2 unsubscribe per topic + client deregistration |
| `heartbeat` | TTL refresh in the `GrpcClientRegistry`; a reaper evicts stale clients (unsubscribes them) |
Group semantics: the legacy `consumerGroup` maps onto a v2 subscription
group; the SDK's default `CLUSTERING` mode maps to `LOAD_BALANCE`
distribution, `BROADCASTING` maps to `BROADCAST`. The clientId is derived
from `consumerGroup` + `env` + `idc` (the 1.x triple).
Non-goals (follow-ups): a new gRPC-native v2 API (HTTP + CloudEvents stays
the primary path), the gRPC admin surface (stays unimplemented as on 1.x),
and Go/Rust SDK verification (the protos are shared; Java SDK is the
conformance suite — see `GrpcLegacyBridgeIntegrationTest`).
## 2. Server-side protocol plugins
The runtime discovers protocol adaptors via the
`org.apache.eventmesh.protocol.api.ProtocolAdaptor` SPI. Active plugins:
* `eventmesh-protocol-plugin/eventmesh-protocol-cloudevents` - **GA**.
HTTP publish / subscribe over CloudEvents JSON. Required by the modern
data plane. Do not deprecate.
* `eventmesh-protocol-plugin/eventmesh-protocol-meshmessage` - **Beta** as
the HTTP / gRPC resolver package, **Legacy** as the TCP resolver
package. The HTTP and gRPC surfaces remain because they carry
EventMeshMessage semantics (used by some existing gRPC clients); the TCP
surface is in maintenance mode and receives only critical bug fixes.
* `eventmesh-protocol-plugin/eventmesh-protocol-a2a` - **Experimental**.
A2A wire contract; routes tasks through the A2A gateway on Runtime.
The `eventmesh-architecture-guard` module enforces that connector plugins
do not depend on `eventmesh-runtime`; the protocol plugins are the
runtime's *internal* extension point and live under
`eventmesh-protocol-plugin/`. Downstream consumers should not depend on
any of the protocol plugins directly - they should depend on the SDK
(see section 3).
## 3. Client SDKs
| SDK | Path | Status | Notes |
| --- | --- | --- | --- |
| Java (CloudEvents) | `eventmesh-sdks/eventmesh-sdk-java/client/cloudevents` | **GA** | The only modern SDK client. Recommended for all new code. |
| Java (gRPC) | `eventmesh-sdks/eventmesh-sdk-java/client/grpc` | **Beta** | For clients that need gRPC framing; backed by the gRPC resolver. |
| Java (TCP) | `eventmesh-sdks/eventmesh-sdk-java/client/tcp` | **Legacy** | Includes the `openmessage`, `cloudevent`, and `eventmeshmessage` impls. The OpenMessaging impl is being phased out (see migration below). |
| C | `eventmesh-sdks/eventmesh-sdk-c` | **Beta** | HTTP + CloudEvents. |
| Go | `eventmesh-sdks/eventmesh-sdk-go` | **Beta** | HTTP + CloudEvents. |
| Rust | `eventmesh-sdks/eventmesh-sdk-rust` | **Beta** | HTTP + CloudEvents. |
### 3.1 Java SDK public surface
Starting with this release, the Java SDK's public API surface - i.e. the
classes that downstream consumers should reference - is restricted to:
* `org.apache.eventmesh.client.cloudevents.CloudEventsClient` (and the
`client/cloudevents/stream/*` types for streaming / SSE).
* `org.apache.eventmesh.client.grpc.*` (for clients that need gRPC).
Anything under `org.apache.eventmesh.client.tcp.*` is marked
**Legacy** and is excluded from the SDK's `api` configuration in
Gradle. The `io.openmessaging:openmessaging-api` dependency, which is
only used by the legacy TCP client's OpenMessaging implementation, is
demoted from `api` to `implementation` so that modern users (who only
depend on the CloudEvents client) do not see OMA types in their
classpath.
### 3.2 Migration from legacy TCP / OpenMessaging to CloudEvents HTTP
1. Switch the client to
`org.apache.eventmesh.client.cloudevents.CloudEventsClient` (see
`docs/feature/client-java.md`).
2. The CloudEvents wire format replaces the `EventMeshMessage` / OMA
`Message` envelope. Event payload stays the same.
3. If you depended on the TCP framing for performance reasons, note that
the CloudEvents HTTP path uses HTTP/1.1 keep-alive and SSE for
streaming - comparable latency in the common case.
4. Legacy TCP support continues for at least one more minor release. A
deprecation warning is logged on every legacy client construction;
removal is planned for the next major version (see #5341 follow-up).
## 4. Architecture guardrails
`eventmesh-architecture-guard` enforces, via ArchUnit rules and the
`architecture-guard.yml` CI workflow, that:
* `eventmesh-protocol-plugin/*` modules are partitioned into
`public` (SPI) and `internal` (implementation); the
`public -> internal` direction is allowed, the reverse is not
(see #5297).
* `eventmesh-connector-plugin/*` may not depend on `eventmesh-runtime`
(see #5302 / #5297).
* The runtime's modern ingress path (`UniIngressService`,
`UniHttpServer`) may not import legacy TCP / OMA wire types
(verified by `git grep "import.*MeshMessage\\|import io.openmessaging"`
in `eventmesh-runtime/src/main/` - only the legacy `tcp/` and
`transport/http/LegacyHttp*` packages should match).
## 5. Acceptance
For the #5341 acceptance check, the following must hold:
* `docs/feature/protocols.md` exists and is linked from
`docs/architecture/overview.md` (section 9) and from the README.
* The Java SDK's `build.gradle` declares `io.openmessaging:openmessaging-api`
as `implementation`, not `api`.
* `git grep "import.*MeshMessage\\|import io.openmessaging"`
in `eventmesh-runtime/src/main/` returns only files under
`runtime/tcp/`, `runtime/transport/http/LegacyHttp*`, or
`runtime/transport/http/EventMeshMessageHttpCodec` (the legacy HTTP
codec).
* `eventmesh-architecture-guard` continues to pass on the develop branch
after these changes.
## 6. References
* Parent issue: #5296 (Architecture Review, "New review questions" 2026-09-07)
* Tracking issue: #5341
* Architecture: `docs/architecture/overview.md`
* SDK guide: `docs/feature/client-java.md`
* Arch-guard: `eventmesh-architecture-guard/`, `docs/feature/architecture-guard.md`
* A2A wire: `docs/feature/a2a.md`