This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
muxio-rpc-service-endpoint: Server-Side Handler Registry
Loading…
muxio-rpc-service-endpoint: Server-Side Handler Registry
Relevant source files
- extensions/muxio-rpc-service-endpoint/Cargo.toml
- extensions/muxio-rpc-service-endpoint/src/client_read_channel.rs
- extensions/muxio-rpc-service-endpoint/src/endpoint.rs
- extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs
- extensions/muxio-rpc-service-endpoint/src/endpoint_utils.rs
- extensions/muxio-rpc-service-endpoint/src/error.rs
- extensions/muxio-rpc-service-endpoint/src/lib.rs
- extensions/muxio-rpc-service-endpoint/src/with_handlers_trait.rs
- extensions/muxio-rpc-service-endpoint/tests/prebuffered_endpoint_tests.rs
- extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs
The muxio-rpc-service-endpoint crate provides the server-side logic for managing and executing RPC method handlers. It acts as the bridge between the raw bytes received from a transport and the application-specific asynchronous logic defined by the user. It is designed to be runtime-agnostic, supporting both standard threads and tokio via feature flags extensions/muxio-rpc-service-endpoint/Cargo.toml:11-13
Core Entities and Registry
The endpoint maintains a registry of both “pre-buffered” and “streaming” handlers.
- Pre-buffered handlers : The framework ensures the entire request payload is reassembled before the handler is invoked. The handler returns a single response extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs:30-32
- Streaming handlers : Events (Header, PayloadChunk, End, Error) are forwarded to the handler as they arrive. The handler uses a
StreamResponderto send multiple response chunks back extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs:91-96
RpcServiceEndpoint Struct
The RpcServiceEndpoint<C> is the primary concrete implementation of the service registry extensions/muxio-rpc-service-endpoint/src/endpoint.rs:95-102 It is generic over a context type C, which allows applications to pass connection-specific data (like session info or database handles) to every RPC handler extensions/muxio-rpc-service-endpoint/src/endpoint.rs:92-97
Handler Types and Registry Locks
The crate uses the WithHandlers and WithStreamHandlers traits to abstract over different Mutex implementations for the registry maps extensions/muxio-rpc-service-endpoint/src/with_handlers_trait.rs:9-18 extensions/muxio-rpc-service-endpoint/src/with_handlers_trait.rs:56-65
| Entity | Description |
|---|---|
RpcServiceEndpoint<C> | The registry holding the mapping of method IDs to handlers extensions/muxio-rpc-service-endpoint/src/endpoint.rs:95-102 |
RpcPrebufferedHandler<C> | Type alias for an Arc wrapped async closure that returns a Result<Vec<u8>, ...> extensions/muxio-rpc-service-endpoint/src/endpoint.rs:15-26 |
RpcStreamHandler<C> | Type alias for a closure that receives RpcStreamEvent and a StreamResponder extensions/muxio-rpc-service-endpoint/src/endpoint.rs90 |
StreamResponder | A handle used by streaming handlers to write chunks back to the transport. It buffers data if the transport writer isn’t ready yet extensions/muxio-rpc-service-endpoint/src/endpoint.rs:33-37 extensions/muxio-rpc-service-endpoint/src/endpoint.rs:52-65 |
Concurrency and Features
- Standard : Uses
std::sync::Mutex(suitable for WASM or non-Tokio envs) extensions/muxio-rpc-service-endpoint/src/with_handlers_trait.rs:39-51 - Tokio Support : If the
tokio_supportfeature is enabled, it usestokio::sync::Mutexfor non-blocking lock acquisition in async contexts extensions/muxio-rpc-service-endpoint/src/with_handlers_trait.rs:21-35
Sources: extensions/muxio-rpc-service-endpoint/src/endpoint.rs:1-143 extensions/muxio-rpc-service-endpoint/src/with_handlers_trait.rs:1-98 extensions/muxio-rpc-service-endpoint/Cargo.toml:11-14
The Three-Stage Pipeline: read_bytes
The read_bytes function in RpcServiceEndpointInterface implements a pipeline to transform incoming transport bytes into RPC events or responses extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs:150-156
Data Flow Diagram
This diagram maps the read_bytes logic to the internal code entities, distinguishing between prebuffered reassembly and streaming event routing.
graph TD
subgraph "Stage 1: Decode & Route (Synchronous)"
A["Transport Bytes"] --> B["RpcDispatcher::read_bytes()"]
B --> C{"Is Method Streaming?"}
C -- "Yes" --> D["Route to RpcStreamHandler"]
C -- "No" --> E["Accumulate in Dispatcher"]
end
subgraph "Stage 2: Execute (Concurrent)"
E --> F["Identify Finalized IDs"]
F --> G["process_single_prebuffered_request()"]
G --> H["RpcPrebufferedHandler Closure"]
H --> I["Generate RpcResponse"]
end
subgraph "Stage 3: Emit (Synchronous)"
I --> J["RpcDispatcher::respond()"]
D --> K["StreamResponder::respond()"]
J --> L["RpcEmit callback"]
K --> L
L --> M["Transport Write"]
end
style B font-family:monospace
style G font-family:monospace
style H font-family:monospace
style K font-family:monospace
style L font-family:monospace
Sources: extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs:160-250 extensions/muxio-rpc-service-endpoint/src/endpoint_utils.rs:11-87
Pipeline Details
- Stage 1: Decode & Routing: The endpoint first checks if any streaming handlers are registered. If so, it installs a router on the
RpcDispatcherso that incomingHeaderevents for streaming methods get immediate handlers installed, bypassing the prebuffered accumulator extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs:168-185 - Stage 2: Reassembly & Execution: For non-streaming methods, the endpoint calls
dispatcher.read_bytes(bytes)extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs224 It then iterates through returned IDs to find requests whereis_rpc_request_finalizedis true. Completed requests are extracted and executed concurrently usingjoin_allextensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs239 - Stage 3: Response Emission : Prebuffered responses are passed back to
dispatcher.respond()extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs247 Streaming responses are emitted via theStreamResponder, which uses anRpcResponseWritercreated after the read loop to ensure correct framing extensions/muxio-rpc-service-endpoint/src/endpoint.rs:67-84
Sources: extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs:150-250
Handler Registration and Execution
The registration methods ensure that method_id collisions between prebuffered and streaming handlers are prevented extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs:58-67 extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs:116-125
Prebuffered Handler Error Mapping
The process_single_prebuffered_request utility maps handler results to the wire protocol extensions/muxio-rpc-service-endpoint/src/endpoint_utils.rs:11-87
| Result | Status Sent to Client | Payload Behavior |
|---|---|---|
Ok(Vec<u8>) | RpcResultStatus::Success | Contains the returned bytes extensions/muxio-rpc-service-endpoint/src/endpoint_utils.rs:36-42 |
Err(RpcServiceEndpointHandlerError) | Fail, SystemError, or MethodNotFound | Payload is the bitcode encoded RpcServiceErrorPayload extensions/muxio-rpc-service-endpoint/src/endpoint_utils.rs:45-64 |
Err(Generic) | RpcResultStatus::SystemError | Payload contains the string representation of the error extensions/muxio-rpc-service-endpoint/src/endpoint_utils.rs:66-74 |
Sources: extensions/muxio-rpc-service-endpoint/src/endpoint_utils.rs:11-87 extensions/muxio-rpc-service-endpoint/src/error.rs:9-29
Error Types
The crate defines two primary error structures:
RpcServiceEndpointError: Represents failures in the endpoint’s own logic, such asDecodeorEncodefailures, or registration conflicts extensions/muxio-rpc-service-endpoint/src/error.rs:25-29RpcServiceEndpointHandlerError: A special wrapper aroundRpcServiceErrorPayload. Handlers return this to send structured errors (code + message) back to the caller extensions/muxio-rpc-service-endpoint/src/error.rs:9-21
Sources: extensions/muxio-rpc-service-endpoint/src/error.rs:1-52