Repository navigation
Complete R0 SDK feasibility and core transport probes - #1556
Conversation
Pin MCP and grpc-java SDKs in test scope and add bounded interoperability probes over the Restlet HTTP/2 engine. The gRPC prototype exercises the grpc-core client transport SPI and a socket-less Restlet server host for unary exchanges. R0 remains a draft pending streaming, lifecycle, MCP SSE/STDIO, and profile compatibility gates. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Jerome Louvel <374450+jlouvel@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
8f2910b to
b3d6695
Compare
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Exercise stateless tool dispatch, profile header and revision errors, and resultType mapping over shared Restlet HTTP/2. Keep the bridge test-only and bounded to tool methods. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Run a shared 20-request corpus against an isolated real Ikanos capability and the Restlet HTTP/2 prototype. Assert recorded full responses and measured differences by default, with an opt-in live check and bounded subprocess lifecycle. Document the compatibility gaps and defer Ikanos migration. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Align fixture metadata, discovery, legacy initialize rejection, HTTP error mapping and parse-error envelopes with the real Ikanos reference. Keep normal dispatch and JSON serialization in the SDK. Prove the SDK null-response-ID limitation and isolate that parse-error envelope exception. The corpus now has 19 exact matches and one explicit Jackson diagnostic-text difference; reference snapshots are unchanged. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
R0 update: added a bounded, test-only MCP Streamable HTTP GET/listening-SSE probe using the SDK session seam, with SDK-generated event IDs and replay after a known Last-Event-ID. Event history is capped at eight entries; unknown/expired IDs return HTTP 400. MCP SDK 2.1.0's session replay hook is empty, so replay is explicitly probe-owned rather than SDK support or a production adapter. Validation: the full focused R0 selector with the live Ikanos differential enabled passed (12 tests, 0 failures, 0 errors, 0 skipped). |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
R0 update: added finite gRPC BIDI_STREAMING probes through official SDK APIs in both directions, exchanging two requests and two responses. The current Restlet client buffers requests until half-close, while the Restlet-hosted server dispatches buffered requests before writing collected responses; this validates the SDK bidi method path but is not full-duplex streaming and does not establish demand/back-pressure or cancellation. Validation: full focused R0 selector with live Ikanos differential enabled passed (12 tests, 0 failures, 0 errors, 0 skipped). Commit: 082fc6a. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Follow-up: replaced the earlier buffered bidi probe with actual message-level full-duplex exchange using Restlet's existing HTTP/2 streaming request/response support. Both directions now send one request and assert its response arrives before sending the next request or half-closing. The Restlet-backed client uses a bounded pipe to stream request frames while consuming response frames; the test Restlet server reads incoming frames concurrently with writing bounded queued responses. This shows the core connector can carry full-duplex gRPC traffic; no production Netty change was needed, but the SDK transport bridge remains a test-only prototype with handwritten framing. Demand/flow-control conformance, cancellation, and long-lived lifecycle remain open. Verification: full R0 selector plus Http2FullDuplexTestCase passed with live Ikanos enabled (13 tests, 0 failures/errors/skips). Commit f4ce572. |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Next R0 gate: test bridge now honors gRPC |
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
R0 cancellation update (a817742): both interop directions now cancel an established bidi call after its first response, without request half-close. Assertions cover one client CANCELLED terminal callback, one remote SDK cancellation callback, bridge reader/writer completion, repeated cancellation, and a successful follow-up unary call on the same channel. The test client records cancellation before aborting HTTP I/O; the test server exposes cancellation state and closes its request-demand gate before notifying the SDK. A separate regression verifies that closing demand wakes a blocked receiver and later credits do not reopen it. No production connector changes were needed. Validation: focused gRPC + Http2CancellationTestCase passed (4 tests). The combined R0 + HTTP/2 full-duplex/cancellation run passed 14 of 15 tests, including live Ikanos; the remaining MCP STDIO test hit its previously observed 5-second initialization timeout and passed in an isolated rerun. This is not a claim of a clean combined run. Pre-header cancellation races, server-initiated cancellation, complete flow-control conformance, metadata and long-lived lifecycle remain open. |
Verify socket-less grpc-java runtime hosting, native status and metadata, pre-header cancellation, active shutdown and SDK module isolation. Fix multiplexed response-head delivery and headers-only completion. Record scoped protocol decisions and delivery follow-ups. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Signed-off-by: Jerome Louvel <374450+jlouvel@users.noreply.github.com>
|
R0 closeout published at d5d9b17. The closing live SDK + HTTP/TLS/HTTP3/SSE selector passed 107/107 (no skips), and the final tightened SDK-host/transport rerun passed 9/9. The published GitHub build and both SonarCloud checks now pass: https://github.com/restlet/restlet-framework-java/actions/runs/39694386959 . PR is ready for R0 review, not merged. README and the refreshed PR body contain the supported-feature matrix, measured core fixes, explicit unsupported controls, limited-go/no-go decisions and separate protocol/core delivery issues. R1-R6 extension delivery and Ikanos migration remain gated; R0 manual framing is not a production fallback. |
|
@thboileau Could you review this PR, part of a stack of three preparation for foundation for support of gRPC, MCP and Smithy on top of Restlet 3 / Netty 4.2 reusing a maximum of the official SDKs/libraries? |
There was a problem hiding this comment.
🟡 Changes recommended
Zero-length HTTP/2 and HTTP/3 responses can close prematurely and lose delayed trailers, while shutdown tests do not verify cancellation and worker completion for every active call.
3 open issues
What changed in this PR
Completes the R0 feasibility probes for SDK-backed MCP and native gRPC integration over Restlet, without adding production RPC extensions. The results support scoped implementation work, while Ikanos migration remains deferred.
Changes:
- Adds test-only SDK interoperability, lifecycle, module-loading, and Ikanos differential probes.
- Updates multiplexed transport handling for header-before-body delivery and headers-only response completion.
- Documents measured results, limitations, reproduction commands, and follow-up work.
| File | Description |
|---|---|
| readme.md | Documents R0 evidence, decisions, boundaries, and reproduction steps. |
| org.restlet/src/test/resources/mcp-ikanos/observations.json | Records the 20-case compatibility baseline. |
| org.restlet/src/test/resources/mcp-ikanos/IkanosReferenceEndpoint.java | Hosts the isolated live Ikanos reference endpoint. |
| org.restlet/src/test/java/org/restlet/engine/connector/RpcSdkBoundaryTestCase.java | Checks module identities and service loading without official gRPC network transports. |
| org.restlet/src/test/java/org/restlet/engine/connector/McpStreamableSdkTransportSpikeTestCase.java | Probes MCP sessions, SSE notifications, and bounded replay. |
| org.restlet/src/test/java/org/restlet/engine/connector/McpStdioSdkServerProcess.java | Supplies the SDK STDIO subprocess fixture. |
| org.restlet/src/test/java/org/restlet/engine/connector/McpSdkTransportSpikeTestCase.java | Exercises MCP HTTP/2, STDIO, and profile compatibility. |
| org.restlet/src/test/java/org/restlet/engine/connector/McpIkanosDifferentialProbe.java | Compares recorded and live Ikanos responses. |
| org.restlet/src/test/java/org/restlet/engine/connector/Http2FullDuplexTestCase.java | Adds the header-before-body regression. |
| org.restlet/src/test/java/org/restlet/engine/connector/GrpcSdkTransportSpikeTestCase.java | Adds diagnostic gRPC interoperability, metadata, demand, and cancellation probes. |
| org.restlet/src/test/java/org/restlet/engine/connector/GrpcSdkServerHostSpikeTestCase.java | Tests socket-less hosting with SDK-owned runtime and framing. |
| org.restlet/src/main/java/org/restlet/engine/netty/NettyServerCall.java | Ends eligible empty multiplexed responses in initial headers. |
| org.restlet/src/main/java/org/restlet/engine/netty/NettyClientCall.java | Removes the multiplexed response-body peek before header delivery. |
| org.restlet/pom.xml | Pins test-scope MCP and gRPC dependencies. |
| changes.md | Records the transport changes and feasibility probes. |
Review effort: Balanced
Defer the automatic release of a zero-length HTTP/2 or HTTP/3 response entity until the response completes, so the stream is not reset before its trailing HEADERS arrive. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Keep both calls active until channel shutdown, and await the I/O worker completion of every call in both transport directions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|





R0 outcome
Complete the bounded SDK feasibility/decision phase on Restlet 3.0 / Java 25. Limited go for unary-first native gRPC integration and MCP SDK-supported profiles; no-go for Ikanos migration. This is not production extension delivery or full streaming conformance. No shared RPC abstraction and no second production HTTP engine.
Implementation and evidence
Two measured, protocol-neutral core fixes
Existing late-first-trailer support already passes its regression and was not reimplemented.
Ikanos differential result
A shared 20-request corpus runs against a real endpoint in a separate JVM with Ikanos dependencies, a real capability and a deterministic loopback upstream; resource/dispatcher/tool handlers are not mocked. Reference observations were revalidated at
932f2322d7dcf4ec973f650f3daf5e9ddf1b4c71.19/20 exact full status/body matches. The remaining difference is precisely
/body/error/messagefor Jackson 2 versus Jackson 3 malformed-JSON diagnostics. HTTP 400, -32700 and null ID agree. Messages and absent fields are not normalized away. Fixture-specific discovery/metadata and a narrow null-ID envelope are explicit compatibility exceptions; normal tools use SDK dispatch/codecs. Direct SDK revision/session behavior remains incompatible with the current Ikanos profile. This is not full profile equivalence or migration approval.Validation
Scoped decisions / delivery tracking
The manual framing/direct-handler bidi fixtures remain diagnostic only and must not become production fallbacks. SDK-owned streaming transports/readiness, generated stubs, pre-registration/server cancellation races, idle disconnects, DNS/LB/subchannels, connection/TLS authority separation, GOAWAY/draining/keepalive, complete MCP HTTP validation and long-lived/native-image lifecycle remain R1-R6 delivery/conformance gates. Borrowed resource sharing does not establish process-global Netty pools. No Ikanos source was copied into the new probes; preserve attribution before any future extraction.