fix(protocol): single protocol path — EventMeshFrame across HTTP ingress, filter chain and TCP egress (#5299) - #5319
Conversation
…pache#5299 Sub-PR A) The HTTP ingress path now converts structured CloudEvents JSON bytes to EventMeshFrame at the boundary via FrameAdaptor SPI, so UniIngressService no longer imports io.cloudevents.CloudEvent on the HTTP code path. New ingress methods (Frame-typed): - publishBatchFrames(topic, List<EventMeshFrame>) - publishLiteFrame(parent, lite, EventMeshFrame) - pollLiteFrames(parent, lite, max, timeoutMs) -> List<EventMeshFrame> - requestFrame(topic, EventMeshFrame, timeout) -> EventMeshFrame - replyFrame(correlationId, EventMeshFrame) The CloudEvent-typed overloads are preserved for binary compatibility with the TCP bridge. Sub-PR B will migrate FilterChain; Sub-PR C will migrate the TCP path. Closes part of apache#5299.
cf0d068 to
69e808f
Compare
|
Force-pushed |
…#5299 Sub-PR B) The ingress security pipeline (§4.5) — TokenAuthFilter / AclFilter / SignatureVerifierFilter / FilterChain — now operates on the runtime's internal wire format (org.apache.eventmesh.common.wire.EventMeshFrame) instead of io.cloudevents.CloudEvent. This continues the apache#5299 single- protocol-path migration: sub-PR A routed the HTTP ingress through the FrameAdaptor SPI; sub-PR B extends the same boundary inward to the filter chain so that auth/acl/signature now read directly from frame.attributes(). Changes: - IngressFilter: new check(EventMeshFrame, FilterContext) primary method; the CloudEvent overload is now a default that bridges via EventMeshFrame.fromCloudEvent(...) for backward compat. - FilterChain: new check(EventMeshFrame, FilterContext) overload; CloudEvent variant is deprecated and bridges via fromCloudEvent. - AclFilter: implement check(EventMeshFrame, ...) — also rejects non-EVENT frames (e.g. STREAM_REQ / STREAM_CHUNK) since the ingress security pipeline is event-shaped only. - TokenAuthFilter: implement check(EventMeshFrame, ...) — credential still comes from FilterContext (HTTP Authorization header), so the frame body is unused for this stage. - SignatureVerifierFilter: implement check(EventMeshFrame, ...) — signature travels in frame.attributes() under the same key (emsignature) the legacy CloudEvent extension used, so signed CloudEvents round-trip transparently through the cloudevents FrameAdaptor. - UniHttpServer: drop the temporary frame.toCloudEvent() bridge in the publish() filter call; thread tenant directly from frame.attributes(). Also drop the synthetic CloudEvent stub used for pre-publish security check — replaced with a minimal EventMeshFrame.event(emptyMap, []). - New test class: EventMeshFrameFilterTest (6 tests) exercising the EventMeshFrame-typed path parallel to the existing SecurityFilterTest which still covers the CloudEvent bridge. Backward compat: existing custom filters implementing IngressFilter.check(CloudEvent, ...) keep working because the interface now provides a default implementation. They will compile unchanged and continue to be invoked via the deprecated chain overload until sub-PR C migrates the TCP path and we can drop the bridge entirely. Refs apache#5299.
|
Force-pushed Sub-PR A (commit Sub-PR B (commit Diff: 8 files, +1247 / -958. The CloudEvent-based filter methods remain as @deprecated bridges so existing custom filters keep compiling; they will be removed in sub-PR C after the TCP path migrates. CI is being re-triggered on the new head. |
…x + C + D) Sub-PR B fix: - restore the missing io.cloudevents.CloudEvent import in IngressFilter (broke compileJava) - move EventMeshFrame into the correct checkstyle ImportOrder group (style/checkStyle.xml puts org.apache.eventmesh first; maxWarnings=0 so it fails CI) - update SecurityFilterTest for the frame-based SignatureVerifierFilter.canonical(...) Sub-PR C: migrate the TCP egress path to EventMeshFrame - TcpFrameCodec.encodePush / TcpPushChannel.deliver now take an EventMeshFrame directly, dropping the frame -> CloudEvent -> wire round trip - delete the dead CloudEvent-era egress SPI: CloudEventToPackageBody, MeshEventToPackageBody - UniTcpServer drops the now-unused bodyMapper constructor parameter - TCP ingress was already frame-native (MeshMessagePackageRouter / TcpRequest / NettyTcpPushChannel) Sub-PR D: document the apache#5299 acceptance matrix and protocol status labels (docs/eventmesh-uni-architecture-redesign.md section 19.6) Refs apache#5299.
|
Folded the remaining #5299 sub-PRs into this PR ( Sub-PR A ( Sub-PR B ( Sub-PR C (
Sub-PR D ( This commit also fixes two defects the previous head introduced:
Verified locally on JDK 21: |
Issue #5299 Sub-PR A: route UniHttpServer ingress through FrameAdaptor SPI
Summary
The HTTP ingress path now converts structured CloudEvents JSON bytes to
EventMeshFrameat the boundary via theFrameAdaptorSPI(
CloudEventsFrameAdaptor).UniIngressServiceno longer needs to importio.cloudevents.CloudEventon the HTTP code path. The runtime primarypath is now Frame-in / Frame-out; the CloudEvent-typed ingress methods
(
publish/publishBatch/request/reply/publishLite/pollLite) are preserved unchanged for binary compatibility with the TCPbridge and out-of-tree callers.
New public methods on
UniIngressServicepublishBatchFrames(topic, List<EventMeshFrame>)FrameAdaptor.toFrameper array element, then this methodpublishLiteFrame(parent, lite, EventMeshFrame)/events/lite/publishpollLiteFrames(parent, lite, max, timeoutMs) → List<EventMeshFrame>/events/lite/pollresponse body serialized back to CloudEvents JSON by the egress adapterrequestFrame(topic, EventMeshFrame, timeout) → EventMeshFramereplyFrame(correlationId, EventMeshFrame)The CloudEvent-typed overloads are kept for binary compatibility with the
TCP bridge and out-of-tree callers. They will be deprecated in sub-PR B
once the TCP path also migrates to the
MeshMessageFrameAdaptor.UniHttpServer changes (8 ingress call sites)
POST /events/publishEventFormatProvider.deserialize(body)FrameAdaptors.get("cloudevents").toFrame(new ByteTransport(body))POST /events/publishBatchpublishBatch(List<CE>)publishBatchFrames(List<Frame>)POST /events/lite/publishEventFormatProvider.deserialize(body)FrameAdaptor.toFrame(...)+publishLiteFrame(...)GET /events/lite/pollEventFormatProvider.serialize(ce)per eventFrameAdaptor.toCloudEventsJson(frame)per eventPOST /request(blocking req-reply)EventFormatProvider.deserialize(body)+request(CE)FrameAdaptor.toFrame(...)+requestFrame(...); response body viaFrameAdaptor.toCloudEventsJson(reply)POST /events/replyEventFormatProvider.deserialize(body)+reply(CE)FrameAdaptor.toFrame(...)+replyFrame(...)GET /events/poll(egress)FrameAdaptors.toCloudEventsJson(be.getEvent())UniHttpServerno longer importsio.cloudevents.*. The 5 importsFrameAdaptor/ByteTransport/EventMeshFrameare added.Security stub — temporary bridge (sub-PR B scope)
The
filterChain.check(stubEvent, ctx)ACL check insideUniHttpServer.publishstill consumes a
CloudEvent. ATODO(#5299 sub-PR B)comment marks the spot.The next sub-PR will:
FilterChain.check(EventMeshFrame, FilterContext)overloadUniHttpServerpass the Frame directly to the filter chainCloudEventFilter/AclFilter/SignatureVerifierFilter/TokenAuthFilterto look up extensions from Frame attributesUntil then, the HTTP path does a one-shot
frame.toCloudEvent()for theACL call only. This is a runtime hot-path minor cost (one allocation per
request) that the next sub-PR removes.
Acceptance against #5299
EventMeshFrame,not a protocol-specific envelope type
(CE is already primary; MeshMessage and A2A follow in sub-PR C
and existing sub-PR D)
FrameAdaptorSPI — no directEventFormatProvidercalls inUniHttpServercoreSDK package has no Netty / gRPC / OpenMessaging — out ofscope (issue marks this as a follow-up)
done in sub-PR D
Verification
./gradlew.bat :eventmesh-runtime:compileJava --offline→ BUILD SUCCESSFUL,0 errors, no new warnings (45 deprecation warnings all pre-existing)
./gradlew.bat :eventmesh-runtime:checkstyleMain :eventmesh-runtime:checkstyleTest --offline→ BUILD SUCCESSFUL, 0 violations
./gradlew.bat :eventmesh-runtime:test --offline --tests "*UniIngressServiceTest*" --tests "*UniHttpServer*Test*" --tests "*SecurityWiringTest*" --tests "*SseStreamTest*"→ BUILD SUCCESSFUL, 17 tests, 0 failures, 0 ignoredFiles changed
eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/http/UniHttpServer.java(61 +/29 -)
eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/ingress/UniIngressService.java(67 +/2 -)
Follow-up
SignatureVerifierFilter / TokenAuthFilter) to accept
EventMeshFrameUniTcpServer+MeshMessagePackageRouter)to use
MeshMessageFrameAdaptorprotocol labels, sdk.core/sdk.streaming/sdk.a2a/sdk.legacy discussion