This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Muxio Overview
Loading…
Muxio Overview
Relevant source files
Muxio is a high-performance, transport-agnostic framework designed for layered stream multiplexing and schemaless RPC communication in Rust Cargo.toml:3-4 It provides a modular toolkit that separates low-level binary framing from high-level service logic, allowing developers to build bidirectional, efficient communication protocols that run seamlessly across native and WASM environments README.md:20-27
System Architecture: From Bytes to Services
The Muxio ecosystem is organized into a hierarchy of layers. At the bottom is a compact binary framing protocol; in the middle is an RPC multiplexing engine; and at the top are specialized transport implementations for Tokio, IPC, and WASM README.md:22-27 README.md:50-55
Conceptual Layering and Code Entities
The following diagram illustrates how the natural language concepts of the “Muxio Stack” map to specific code entities and crates within the workspace.
Muxio Layer Mapping
graph TD
subgraph "Service_Layer_[High-Level]"
A["RpcMethodPrebuffered"] -- "defines" --> B["example-muxio-rpc-service-definition"]
C["RpcServiceCallerInterface"] -- "implemented_by" --> D["RpcClient / RpcWasmClient"]
E["RpcServiceEndpointInterface"] -- "implemented_by" --> F["RpcServer / RpcServiceEndpoint"]
end
subgraph "Core_Layer_[Multiplexing]"
G["RpcSession"] -- "manages" --> H["RpcDispatcher"]
H -- "fragments_into" --> I["Frame"]
I -- "contains" --> J["FrameKind"]
end
subgraph "Transport_Layer_[I/O]"
K["muxio-tokio-rpc-server"] -- "provides" --> L["RpcServer"]
M["muxio-tokio-rpc-client"] -- "provides" --> N["RpcClient"]
O["muxio-wasm-rpc-client"] -- "provides" --> P["RpcWasmClient"]
Q["muxio-tokio-rpc-ipc-server"] -- "provides" --> R["IpcServer"]
end
B -.-> H
D -.-> H
F -.-> H
L -.-> G
N -.-> G
P -.-> G
R -.-> G
Sources: Cargo.toml:16-32 README.md:22-27 README.md:50-55 DRAFT.md:43-48
Workspace Structure
Muxio uses a Cargo workspace to manage its core library and various extension crates. This structure ensures that the core remains lightweight and runtime-agnostic, while providing “batteries-included” support for common runtimes via extensions Cargo.toml:16-32
| Category | Crate Name | Purpose |
|---|---|---|
| Core | muxio / muxio-core | Foundational binary framing and RPC dispatching logic Cargo.toml:3-4 Cargo.toml19 |
| Service Abstraction | muxio-rpc-service | Shared traits and macros like rpc_method_id! for defining RPC contracts Cargo.toml23 README.md40 |
| Interfaces | muxio-rpc-service-caller, muxio-rpc-service-endpoint | Traits for making calls and handling requests Cargo.toml:24-25 |
| Transports | muxio-tokio-rpc-*, muxio-wasm-rpc-client | Runtime-specific implementations for Tokio (WS/IPC) and WASM Cargo.toml:27-31 |
| Examples | example-muxio-ws-rpc-app | Demonstrates end-to-end integration Cargo.toml21 |
For a detailed breakdown of the folder structure and how to build the project, see Getting Started & Workspace Layout.
Sources: Cargo.toml:16-32 README.md:50-55
Design Philosophy
Muxio is built around a “Binary-First” and “Symmetric” philosophy. Unlike many RPC frameworks that assume a Client-to-Server request-response model, Muxio treats both ends of a connection as equal peers capable of initiating and receiving multiplexed streams DRAFT.md:9-25
Key Principles
- Runtime Agnostic : The core library uses a callback-driven model rather than forcing a specific async runtime DRAFT.md:43-48
- Binary Efficiency : Compact binary framing protocol with only 17 bytes of header overhead per frame README.md44
- WASM Compatibility : Designed to bridge Rust logic with JavaScript environments via a byte-passing bridge README.md53 README.md62
- Compile-Time Method IDs : Uses
xxHash3at compile time viarpc_method_id!to avoid runtime string hashing or magic numbers README.md40
For a deep dive into the architectural principles and the “Layered Transport Kit” concept, see Design Goals & Architecture Principles.
Sources: README.md:31-48 DRAFT.md:9-25 DRAFT.md:43-48
Core Multiplexing Flow
The framework operates by interleaving Frame entities over a single transport. The RpcDispatcher coordinates these frames, ensuring that multiple concurrent requests (identified by unique Stream IDs) do not block one another README.md32 README.md44
Data Flow: From Application to Wire
Sources: README.md:32-48 DRAFT.md:43-48 Cargo.toml:58-65
Next Steps
To explore specific areas of the Muxio framework, refer to the following child pages:
- Getting Started& Workspace Layout: Setup instructions, dependency management, and running the examples.
- Design Goals& Architecture Principles: In-depth look at the philosophy behind the framework’s design, including its runtime-agnostic and binary-first goals.
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Core Library: Frame & RPC Layers
Loading…
Core Library: Frame & RPC Layers
Relevant source files
- core/README.md
- core/src/constants.rs
- core/src/frame.rs
- core/src/frame/README.md
- core/src/frame/frame_codec.rs
- core/src/lib.rs
- core/src/rpc.rs
The muxio-core library provides the foundational primitives for bidirectional, multiplexed communication over a byte stream. It is architected into two primary layers: the Frame Layer , which handles binary serialization and stream multiplexing, and the RPC Layer , which manages request-response correlation and stream lifecycles.
Layered Architecture Overview
The core library transforms a raw byte-oriented transport into a structured RPC system through a tiered approach. The frame module handles the physical layout of data on the wire, while the rpc module provides the logical abstractions for multi-channel communication.
| Layer | Responsibility | Key Entities |
|---|---|---|
| RPC Layer | Stream IDs, Request/Response correlation, Dispatching | RpcDispatcher, RpcRequest, RpcResponse |
| Frame Layer | Binary framing, Length-prefixing, Kind-tagging | Frame, FrameCodec, FrameMuxStreamDecoder |
graph TD
subgraph "Frame Layer (core/src/frame/)"
A["FrameCodec"] -- "decodes" --> B["Frame"]
B -- "contains" --> C["FrameKind"]
D["FrameMuxStreamDecoder"] -- "assembles" --> B
end
subgraph "RPC Layer (core/src/rpc/)"
E["RpcDispatcher"] -- "manages" --> F["RpcRequest/Response"]
F -- "contains" --> G["RpcHeader"]
E -- "routes to" --> H["RpcRespondableSession"]
end
B -- "Payload" --> F
The following diagram illustrates the relationship between these layers and their corresponding code entities:
System Entity Mapping: Frame to RPC Transition
Sources: core/src/lib.rs:1-2 core/src/frame.rs:1-13 core/src/rpc.rs:1-7
Frame Layer: Binary Framing Protocol
The Frame Layer is the lowest abstraction in muxio. It defines the binary protocol used to encapsulate data. Every message sent over the wire is wrapped in a Frame core/src/frame/frame_struct.rs:8-14 which includes a header specifying the FrameKind (e.g., Open, Data, End, or Cancel) core/src/frame/frame_kind.rs:10-23 and the payload length.
Key responsibilities of this layer include:
- Serialization : The
FrameCodechandles the conversion betweenFramestructs and raw bytes using little-endian encoding core/src/frame/frame_codec.rs:20-48 - Multiplexing : The
FrameMuxStreamDecoderallows multiple logical streams to be interleaved over a single physical connection by tracking and reassembling frame sequences core/src/frame/frame_mux_stream_decoder.rs:14-20 - Encoding : The
FrameStreamEncoderprovides the mechanism to split larger payloads into smaller chunks and write structured frames back into a byte stream core/src/frame/frame_stream_encoder.rs:13-21
For a deep dive into the binary format and framing mechanics, see Frame Layer: Binary Framing Protocol.
Sources: core/src/frame.rs:1-13 core/src/constants.rs:2-7 core/src/frame/README.md:19-30
RPC Layer: Dispatcher, Sessions & Stream Lifecycle
The RPC Layer sits atop the Frame Layer and introduces the concept of stateful communication. While the Frame Layer only knows about “packets,” the RPC Layer understands “requests,” “responses,” and “streams.”
The central logic is managed via the RpcDispatcher core/src/rpc.rs5 which maintains a registry of active sessions. When a response arrives, the dispatcher uses the RPC header information to correlate that response with the original request that initiated the session.
Key features include:
- Message Correlation : Tracking unique RPC IDs to match
RpcRequestcore/src/rpc/rpc_request_response.rs:10-18 with correspondingRpcResponsecore/src/rpc/rpc_request_response.rs:20-27 - Message Types : Differentiation between requests, responses, and stream updates via
RpcMessageType(internal to RPC header logic). - Stream Abstraction : High-level interfaces for reading and writing bytes associated with a specific RPC call via
RpcStreamEncoderandRpcStreamDecoder. - Respondable Sessions : The
RpcRespondableSessionallows for pre-buffering and catch-all handling of incoming RPC calls.
For details on how requests are correlated and how the stream lifecycle is managed, see RPC Layer: Dispatcher, Sessions& Stream Lifecycle.
Data Flow: From Bytes to RPC Dispatch
Sources: core/src/frame/frame_codec.rs:68-127 core/src/rpc/rpc_dispatcher.rs:1-10 core/src/rpc/rpc_request_response.rs:1-30
Core Utilities and Constants
The core library also provides shared constants and utilities used by both layers:
- Frame Constants : Defines protocol-wide offsets and field sizes for
Frameheaders, includingFRAME_HEADER_SIZE(21 bytes) core/src/constants.rs:2-7 - RPC Constants : Defines offsets for the RPC header within the frame payload, such as
RPC_FRAME_METHOD_ID_OFFSETandRPC_FRAME_MSG_TYPE_OFFSETcore/src/constants.rs:12-37 - Utils : Contains helper functions for timestamping and atomic ID generation core/src/utils.rs:1-6
Sources: core/src/lib.rs:4-5 core/src/constants.rs:1-38
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Frame Layer: Binary Framing Protocol
Loading…
Frame Layer: Binary Framing Protocol
Relevant source files
- core/README.md
- core/src/constants.rs
- core/src/frame.rs
- core/src/frame/README.md
- core/src/frame/frame_codec.rs
- core/src/frame/frame_error.rs
- core/src/frame/frame_kind.rs
- core/src/frame/frame_mux_stream_decoder.rs
- core/src/frame/frame_stream_encoder.rs
- core/src/frame/frame_struct.rs
The Frame Layer is the foundational transport-agnostic layer of the Muxio library. It provides a binary-first protocol for multiplexing multiple logical streams over a single physical connection (e.g., TCP, WebSockets, or UDP). It handles serialization, chunking, sequencing, and out-of-order reassembly of binary data.
1. Data Structures & Constants
The core unit of communication is the Frame struct core/src/frame/frame_struct.rs:13-48 Every frame contains a fixed-size header followed by a variable-length payload.
Frame Structure
| Field | Type | Description |
|---|---|---|
stream_id | u32 | Identifies the logical stream core/src/frame/frame_struct.rs18 |
seq_id | u32 | Monotonically increasing sequence number for ordering core/src/frame/frame_struct.rs25 |
kind | FrameKind | The control type of the frame (Open, Data, End, etc.) core/src/frame/frame_struct.rs33 |
timestamp_micros | u64 | Send timestamp in microseconds (UNIX epoch) core/src/frame/frame_struct.rs40 |
payload | Vec<u8> | The actual binary data core/src/frame/frame_struct.rs47 |
FrameKind Enum
The FrameKind core/src/frame/frame_kind.rs:5-12 determines the lifecycle state of a logical stream:
Open (0): Initiates a stream; may contain initial data core/src/frame/frame_kind.rs6Data (1): Standard data transmission core/src/frame/frame_kind.rs7End (2): Graceful termination; no further frames will be sent core/src/frame/frame_kind.rs8Cancel (3): Immediate termination; remaining buffered frames should be discarded core/src/frame/frame_kind.rs9Ping (5)/Pong (4): Connectivity and latency checks core/src/frame/frame_kind.rs:10-11
Binary Layout
The protocol uses a fixed header size (21 bytes) core/src/constants.rs7 All multi-byte integers are encoded in Little-Endian format core/src/frame/frame_codec.rs:38-44
| Offset | Size | Field |
|---|---|---|
| 0 | 4 | Total Payload Length (u32) core/src/frame/frame_codec.rs38 |
| 4 | 4 | Stream ID (u32) core/src/frame/frame_codec.rs41 |
| 8 | 4 | Sequence ID (u32) core/src/frame/frame_codec.rs42 |
| 12 | 1 | Frame Kind (u8) core/src/frame/frame_codec.rs43 |
| 13 | 8 | Timestamp (u64) core/src/frame/frame_codec.rs44 |
| 21 | Var | Payload Data core/src/frame/frame_codec.rs45 |
Sources: core/src/frame/frame_struct.rs:13-48 core/src/frame/frame_kind.rs:5-12 core/src/frame/frame_codec.rs:34-48 core/src/constants.rs:1-7
2. Encoding and Decoding Logic
The FrameCodec core/src/frame/frame_codec.rs18 provides the stateless logic for converting between Frame objects and raw bytes.
encode(&Frame) -> Vec<u8>: Serializes the header and appends the payload. It pre-allocates the exact capacity needed (FRAME_HEADER_SIZE + payload.len()) to avoid multiple reallocations core/src/frame/frame_codec.rs:34-48decode(&[u8]) -> Result<DecodedFrame, FrameDecodeError>: Validates that the buffer is at leastFRAME_HEADER_SIZEcore/src/frame/frame_codec.rs:69-71 It returns aDecodedFramewhich wraps theFrameand an optional error core/src/frame/frame_struct.rs:51-54
Error Types
Errors are categorized into FrameEncodeError core/src/frame/frame_error.rs:4-12 and FrameDecodeError core/src/frame/frame_error.rs:27-37 Key errors include:
CorruptFrame: Data does not match the expected protocol format core/src/frame/frame_error.rs5 core/src/frame/frame_error.rs28IncompleteHeader: The buffer provided to the decoder is too small to read the header or the full payload core/src/frame/frame_error.rs36ReadAfterCancel/WriteAfterCancel: Attempting I/O on a stream that has been terminated viaCancelcore/src/frame/frame_error.rs11 core/src/frame/frame_error.rs33
Sources: core/src/frame/frame_codec.rs:9-128 core/src/frame/frame_error.rs:1-54 core/src/frame/frame_struct.rs:51-54
3. Stream Management
FrameStreamEncoder
The FrameStreamEncoder core/src/frame/frame_stream_encoder.rs:11-23 converts a continuous stream of bytes into a sequence of Frame objects for a single stream_id.
- Chunking : It accepts arbitrary byte slices via
write_bytesand splits them into chunks ofmax_chunk_sizecore/src/frame/frame_stream_encoder.rs:63-91 - State Tracking : It maintains the
next_seq_idand transitions thenext_kindfromOpentoDataafter the first frame is emitted core/src/frame/frame_stream_encoder.rs:86-87 - Callback Emission : Encoded bytes are passed to an
on_emitclosure, allowing integration with various transports (e.g., writing to a WebSocket) core/src/frame/frame_stream_encoder.rs:47-59
FrameMuxStreamDecoder
The FrameMuxStreamDecoder core/src/frame/frame_mux_stream_decoder.rs:31-34 is a stateful, multiplexed reassembler. Unlike the encoder, one decoder handles all active streams on a connection.
- Buffering : It maintains a
Vec<u8>for partial frames that haven’t fully arrived across the wire core/src/frame/frame_mux_stream_decoder.rs32 core/src/frame/frame_mux_stream_decoder.rs71 - Reassembly : It uses a
HashMap<u32, StreamReassembly>to tracknext_expectedsequence IDs for every stream core/src/frame/frame_mux_stream_decoder.rs33 core/src/frame/frame_mux_stream_decoder.rs:36-41 - Out-of-Order Handling : Frames arriving out of order are stored in a
BTreeMapkeyed byseq_idcore/src/frame/frame_mux_stream_decoder.rs38 They are only yielded to the application viaFrameDecoderIteratoronce all preceding frames for that stream have been processed core/src/frame/frame_mux_stream_decoder.rs:139-142
Sources: core/src/frame/frame_stream_encoder.rs:11-166 core/src/frame/frame_mux_stream_decoder.rs:31-158
4. System Flow Diagrams
Entity Mapping: Logical to Code
This diagram maps the conceptual framing protocol to the specific Rust entities implementing it.
Sources: core/src/frame/frame_mux_stream_decoder.rs:31-41 core/src/frame/frame_struct.rs:13-48 core/src/frame/frame_stream_encoder.rs:11-23
graph TD
subgraph "Logical Protocol"
["Binary Stream"] --> ["Multiplexed Frames"]
["Multiplexed Frames"] --> ["Stream ID 100"]
["Multiplexed Frames"] --> ["Stream ID 200"]
end
subgraph "Code Entity Space (core/src/frame/)"
direction LR
["FrameMuxStreamDecoder"] -- "manages" --> ["StreamReassembly"]
["FrameCodec"] -- "creates" --> ["Frame"]
["FrameStreamEncoder"] -- "uses" --> ["FrameCodec"]
end
["Multiplexed Frames"] -- "processed by" --> ["FrameMuxStreamDecoder"]
["Frame"] -- "defines" --> ["Multiplexed Frames"]
["Stream ID 100"] -- "tracked by" --> ["StreamReassembly"]
sequenceDiagram
participant App as "Application Layer"
participant Enc as "FrameStreamEncoder"
participant Codec as "FrameCodec"
participant Net as "Physical Transport (TCP/WS)"
participant MuxDec as "FrameMuxStreamDecoder"
App->>Enc: write_bytes(data)
Note over Enc: Chunks data by\nmax_chunk_size [core/src/frame/frame_stream_encoder.rs:73]
Enc->>Codec: encode(Frame)
Codec-->>Enc: Vec<u8> [core/src/frame/frame_codec.rs:34]
Enc->>Net: on_emit(bytes) [core/src/frame/frame_stream_encoder.rs:56]
Net->>MuxDec: read_bytes(bytes) [core/src/frame/frame_mux_stream_decoder.rs:70]
MuxDec->>Codec: decode(chunk) [core/src/frame/frame_mux_stream_decoder.rs:94]
Codec-->>MuxDec: DecodedFrame [core/src/frame/frame_codec.rs:121]
alt Out of Order
MuxDec->>MuxDec: Buffer in BTreeMap [core/src/frame/frame_mux_stream_decoder.rs:137]
else In Order
MuxDec-->>App: Iterator::next() -> Frame [core/src/frame/frame_mux_stream_decoder.rs:50]
end
Data Flow: Encoding to Decoding
The following diagram illustrates the lifecycle of data as it passes through the Frame Layer.
Sources: core/src/frame/frame_stream_encoder.rs:63-91 core/src/frame/frame_mux_stream_decoder.rs:70-157 core/src/frame/frame_codec.rs:20-128
5. Summary of Key Functions
| Component | Function | Role |
|---|---|---|
FrameCodec | encode | Serializes Frame to Vec<u8> core/src/frame/frame_codec.rs34 |
FrameCodec | decode | Deserializes &[u8] to DecodedFrame core/src/frame/frame_codec.rs68 |
FrameStreamEncoder | write_bytes | Accepts data, chunks it, and triggers emission core/src/frame/frame_stream_encoder.rs63 |
FrameStreamEncoder | end_stream | Emits a FrameKind::End to close the stream core/src/frame/frame_stream_encoder.rs122 |
FrameStreamEncoder | cancel_stream | Emits a FrameKind::Cancel for immediate termination core/src/frame/frame_stream_encoder.rs145 |
FrameMuxStreamDecoder | read_bytes | Ingests raw bytes and returns an iterator of ordered frames core/src/frame/frame_mux_stream_decoder.rs70 |
Sources: core/src/frame/frame_codec.rs:1-128 core/src/frame/frame_stream_encoder.rs:1-166 core/src/frame/frame_mux_stream_decoder.rs:1-158
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Getting Started & Workspace Layout
Loading…
Getting Started & Workspace Layout
Relevant source files
- .cargo/deny.toml
- .github/dependabot.yml
- .github/workflows/build-docs.yml
- .github/workflows/rust-lint.yml
- .github/workflows/rust-tests.yml
- .opencode/plans/1782849738403-silent-moon.md
- Cargo.lock
- Cargo.toml
This page provides a technical overview of the rust-muxio repository structure, its dependency management strategy, and the processes for building, testing, and deploying the framework. Muxio is organized as a Cargo workspace to facilitate modular development of its core multiplexing engine and its various transport and service extensions.
Cargo Workspace Structure
The project utilizes a Cargo workspace to manage multiple interconnected crates. This allows for a “layered transport kit” approach where users can opt into specific transport implementations (like Tokio, IPC, or WASM) without pulling in unnecessary dependencies.
Member Crates
The workspace is divided into the core library, extensions, and example applications.
| Category | Crate Path | Description |
|---|---|---|
| Core | . | The root muxio crate which re-exports muxio-core and optional extensions. |
| Core | core/ | The foundational muxio-core containing binary framing and RPC dispatch logic. |
| Extensions | extensions/muxio-rpc-service | Shared traits and macros for defining RPC methods. |
| Extensions | extensions/muxio-rpc-service-caller | Client-side abstractions for making RPC calls. |
| Extensions | extensions/muxio-rpc-service-endpoint | Server-side registry and execution pipeline for RPC handlers. |
| Extensions | extensions/muxio-tokio-mpsc-adapter | MPSC channel wrapper for streaming RPCs. |
| Extensions | extensions/muxio-tokio-rpc-client | Async client implementation using tokio and tokio-tungstenite. |
| Extensions | extensions/muxio-tokio-rpc-server | WebSocket server implementation using axum. |
| Extensions | extensions/muxio-tokio-rpc-ipc-client | Unix Domain Socket / Windows Named Pipe client. |
| Extensions | extensions/muxio-tokio-rpc-ipc-server | Unix Domain Socket / Windows Named Pipe server. |
| Extensions | extensions/muxio-wasm-rpc-client | Browser-compatible client for WASM environments. |
| Testing | extensions/muxio-ext-test | Internal harness for cross-crate integration testing. |
| Examples | examples/example-muxio-rpc-service-definition | Demo of a shared service contract. |
| Examples | examples/example-muxio-ws-rpc-app | End-to-end WebSocket RPC demo application. |
Sources: Cargo.toml:16-32 Cargo.toml:51-65
Shared Dependency Management
Muxio leverages workspace-level dependency inheritance to ensure version consistency across all member crates. Common attributes such as version, edition, and repository are defined once in the root Cargo.toml.
- Workspace Package Metadata: Defines the global version (e.g.,
0.12.0-alpha) and edition (2024). Cargo.toml:34-40 - Dependency Inheritance: Centralized versions for critical libraries like
tokio(1.52.3),axum(0.8.9),bitcode, andfuturesare managed in the[workspace.dependencies]table. Cargo.toml:42-75 - Crate Usage: Individual crates reference these using
workspace = true. The rootmuxiocrate re-exports extensions based on feature flags likerpc-service-callerortokio-rpc-server. Cargo.toml:77-109
Workspace Layout Diagram
The following diagram maps the logical layers of the framework to the physical crate entities within the workspace.
Workspace Entity Map
graph TD
subgraph "Application_Space"
APP["example-muxio-ws-rpc-app"]
DEF["example-muxio-rpc-service-definition"]
end
subgraph "Transport_Extensions"
TOK_S["muxio-tokio-rpc-server"]
TOK_C["muxio-tokio-rpc-client"]
WASM_C["muxio-wasm-rpc-client"]
IPC_S["muxio-tokio-rpc-ipc-server"]
IPC_C["muxio-tokio-rpc-ipc-client"]
MPSC["muxio-tokio-mpsc-adapter"]
end
subgraph "Service_Abstraction"
EP["muxio-rpc-service-endpoint"]
CALL["muxio-rpc-service-caller"]
SVC["muxio-rpc-service"]
end
subgraph "Core_Engine"
ROOT["muxio_(root)"]
CORE["muxio-core"]
end
APP --> DEF
APP --> TOK_S
APP --> TOK_C
TOK_S --> EP
TOK_C --> CALL
WASM_C --> CALL
IPC_S --> EP
IPC_C --> CALL
MPSC --> EP
MPSC --> CALL
EP --> SVC
CALL --> SVC
SVC --> CORE
ROOT --> CORE
DEF --> SVC
Sources: Cargo.toml:16-32 Cargo.toml:51-65 Cargo.toml:98-109
CI/CD Pipeline & Quality Control
The project employs a robust CI/CD suite via GitHub Actions to maintain code quality across different operating systems and feature configurations.
Rust Tests Pipeline
The rust-tests.yml workflow ensures cross-platform compatibility by running the test suite on ubuntu-latest, macos-latest, and windows-latest. [ .github/workflows/rust-tests.yml25-26](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-tests.yml#L25-L26)
Key steps include:
- Cargo All-Features: Validates that the codebase compiles and passes tests under every possible combination of feature flags using
--all-features. [ .github/workflows/rust-tests.yml78](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-tests.yml#L78-L78) - Workspace Testing: Runs
cargo test --workspace --all-features --lib --bins --tests --examplesto include integration tests and examples. [ .github/workflows/rust-tests.yml78](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-tests.yml#L78-L78) - Coverage: Uses
cargo-llvm-covto generate coverage reports. [ .github/workflows/rust-tests.yml104-123](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-tests.yml#L104-L123)
Rust Lint & Security Pipeline
The rust-lint.yml workflow enforces strict coding standards and security audits. [ .github/workflows/rust-lint.yml1-6](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-lint.yml#L1-L6)
- Formatting: Checks compliance with
cargo fmt --all -- --check. [ .github/workflows/rust-lint.yml130-131](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-lint.yml#L130-L131) - Clippy: Runs with
-D warningsto treat all lints as build failures. [ .github/workflows/rust-lint.yml134-135](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-lint.yml#L134-L135) - Unused Dependencies: Uses
cargo-udepsto find unused crates in the workspace. [ .github/workflows/rust-lint.yml61-62](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-lint.yml#L61-L62) - Security Audits:
cargo deny: Validates licenses (allowing MIT, Apache-2.0, etc.) and checks for advisory vulnerabilities. [ .github/workflows/rust-lint.yml142-143](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-lint.yml#L142-L143) [ .cargo/deny.toml1-9](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .cargo/deny.toml#L1-L9)cargo audit: ScansCargo.lockfor crates with known security vulnerabilities. [ .github/workflows/rust-lint.yml146-147](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-lint.yml#L146-L147)
Documentation Deployment
A weekly cron job and manual trigger facilitate the deployment of the documentation to GitHub Pages using a custom DeepWiki generator. [ .github/workflows/build-docs.yml4-7](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/build-docs.yml#L4-L7) [ .github/workflows/build-docs.yml59-64](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/build-docs.yml#L59-L64)
Building and Running the Example
To explore the framework, the example-muxio-ws-rpc-app provides a complete implementation of a WebSocket-based RPC server and client.
sequenceDiagram
participant App as "example-muxio-ws-rpc-app"
participant Server as "muxio_tokio_rpc_server::RpcServer"
participant Endpoint as "muxio_rpc_service_endpoint::RpcServiceEndpoint"
participant Client as "muxio_tokio_rpc_client::RpcClient"
participant Dispatcher as "muxio_core::rpc::RpcDispatcher"
Note over App: Register Handlers
App->>Endpoint: register_prebuffered(MethodID, Handler)
App->>Server: new(Endpoint).serve(addr)
Note over App: Connect Client
App->>Client: new(url).connect()
Note over App: Execute RPC
App->>Client: call_rpc_buffered(Request)
Client->>Dispatcher: call(RequestBytes)
Dispatcher-->>Server: [Binary Frame over WS]
Server->>Endpoint: read_bytes(Frame)
Endpoint->>App: [Execute Handler Logic]
App-->>Endpoint: Response
Endpoint-->>Dispatcher: [Binary Frame over WS]
Dispatcher-->>App: Future Resolves with Response
Data Flow: Example Application
This diagram illustrates the interaction between the example application and the underlying workspace crates, highlighting key types and methods used during an RPC lifecycle.
Example Execution Flow
Sources: Cargo.toml:17-32 Cargo.toml:51-65
Testing Infrastructure: muxio-ext-test
The extensions/muxio-ext-test crate serves as a specialized testing harness to avoid circular dependencies between transport crates and service crates.
- Test Suites: Contains generic test suites like
streaming_handler_testsandmpsc_adapter_teststhat are exercised across different transports (WS, IPC, WASM). [ .opencode/plans/1782849738403-silent-moon.md130-141](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .opencode/plans/1782849738403-silent-moon.md?plain=1#L130-L141) - MPSC Adapter: Provides
ChannelEndpointExtandChannelCallerExtfor simplified streaming usingtokio::mpscchannels. [ .opencode/plans/1782849738403-silent-moon.md30-61](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .opencode/plans/1782849738403-silent-moon.md?plain=1#L30-L61)
Commands
From the root of the workspace:
- Build everything:
cargo build --workspace --all-features - Run tests:
cargo test --workspace --all-features - Run the example app:
cargo run -p example-muxio-ws-rpc-app
Sources: Cargo.toml:16-32 [ .github/workflows/rust-tests.yml78](https://github.com/jzombie/rust-muxio/blob/a2d43b2a/ .github/workflows/rust-tests.yml#L78-L78)
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Design Goals & Architecture Principles
Loading…
Design Goals & Architecture Principles
Relevant source files
The Muxio framework is built on a layered architecture designed to provide high-performance, multiplexed communication while remaining agnostic of specific network transports or async runtimes. This page details the core design philosophy and the architectural patterns that enable its cross-platform capabilities.
Core Design Philosophy
Muxio is engineered to solve the challenges of building modern distributed systems by prioritizing efficiency, type safety, and portability.
- Binary-First Protocol : Unlike text-based protocols (e.g., JSON-RPC), Muxio operates exclusively on raw bytes. This minimizes CPU overhead for parsing and reduces payload size README.md:46-47 It makes zero assumptions about serialization, supporting formats like CBOR, FlatBuffers, or raw bitcode DRAFT.md11
- Framed Transport : All data is transmitted in discrete, ordered binary chunks (frames), allowing for reliable reassembly of interleaved streams README.md32 DRAFT.md13
- Bidirectional Symmetry : The protocol is inherently symmetric; both the “client” and “server” can initiate requests, send streams, and handle responses using the same underlying logic DRAFT.md15 DRAFT.md25
- WASM Compatibility : By avoiding heavy dependencies on OS-specific networking or multi-threaded primitives in the core, Muxio is fully compatible with WebAssembly environments README.md:46-47 DRAFT.md17
- Runtime-Agnostic Model : The core library uses a non-async, callback-driven design. This allows it to be integrated into
tokio, standard library threads, or single-threaded event loops (like browser JS) without imposing a specific execution model DRAFT.md:43-48 - Minimal Overhead : The binary framing protocol uses a compact 17-byte header (Stream ID, Sequence ID, Frame Kind, Timestamp), making it significantly more efficient than HTTP/2 or gRPC for high-frequency small messages README.md:44-45 README.md:58-59
Sources:
Layered Architecture Principles
Muxio follows a “Layered Transport Kit” concept DRAFT.md3 Each layer has a specific responsibility and communicates with adjacent layers through standardized interfaces, primarily read_bytes and write_bytes DRAFT.md5
1. Frame Layer (The Foundation)
The bottom-most layer handles raw binary framing. It is responsible for taking a stream of bytes and identifying Frame boundaries, handling stream_id allocation, and managing FrameKind (Data, Heartbeat, Fin, Cancel, etc.) README.md:44-45
2. RPC Layer (The Dispatcher)
The RPC layer sits atop the Frame layer. It manages the lifecycle of individual “Sessions.” It correlates requests to responses using unique IDs and handles the multiplexing of multiple concurrent RPC streams over the single framed transport README.md:32-35
3. Service Extension Layer
This layer provides high-level abstractions like the RpcServiceCallerInterface and RpcServiceEndpointInterface. It allows developers to define strongly-typed API contracts using traits like RpcMethodPrebuffered and the rpc_method_id! macro for compile-time hashing README.md:40-42 README.md:60-61
4. Transport Implementation Layer
The outermost layer connects the Muxio logic to physical I/O. Examples include RpcServer (WebSockets over Tokio), RpcClient (Native Async), and RpcWasmClient (JavaScript-to-Rust byte bridge) README.md:52-54
Architecture Entity Mapping
The following diagram illustrates how natural language concepts map to specific code entities across the layers.
Muxio Architecture & Code Entity Map
graph TD
subgraph "ApplicationSpace"
Contract["Service Contract"]
Impl["Method Implementation"]
end
subgraph "ServiceExtensionLayer"
Contract -->|implements| RpcMethodPrebuffered["RpcMethodPrebuffered (trait)"]
Endpoint["RpcServiceEndpoint"] -->|registers| RpcMethodPrebuffered
Caller["RpcServiceCallerInterface (trait)"] -->|invokes| RpcMethodPrebuffered
end
subgraph "CoreRpcLayer"
RpcMethodPrebuffered -->|uses| RpcDispatcher["RpcDispatcher (struct)"]
RpcDispatcher -->|manages| RpcSession["RpcSession (struct)"]
RpcSession -->|tracks| StreamID["Stream ID (u32)"]
end
subgraph "CoreFrameLayer"
RpcDispatcher -->|encodes to| Frame["Frame (struct)"]
Frame -->|categorized by| FrameKind["FrameKind (enum)"]
Frame -->|processed by| FrameCodec["FrameCodec (struct)"]
end
subgraph "TransportLayer"
FrameCodec -->|IO_via| RpcServer["RpcServer (Tokio)"]
FrameCodec -->|IO_via| RpcWasmClient["RpcWasmClient (WASM)"]
FrameCodec -->|IO_via| RpcClient["RpcClient (Native)"]
end
Sources:
Data Flow: The Callback-Driven Model
Muxio’s core is “passive.” It does not spawn its own threads or async tasks. Instead, it relies on the transport layer to push bytes into it and provides callbacks for when it needs to send bytes back out DRAFT.md:43-48
- Ingress : The transport (e.g., a WebSocket or IPC socket) receives raw bytes and calls the
read_bytesfunction on theRpcDispatcherorRpcServiceEndpointDRAFT.md5 - Processing : The core decodes the bytes into a
Frame. If it’s an RPC message, theRpcDispatchercorrelates it to a session README.md:32-33 - Dispatch : If the frame represents a new request, the
RpcServiceEndpointlooks up the registered handler using themethod_idREADME.md:40-42 - Egress : When the handler produces a result, it is passed back down. The core calls a provided
emitcallback (often a closure capturing a network sink or a sender task) to send the response bytes back to the transport DRAFT.md:47-48
Bidirectional Data Flow and Interaction
Sources:
Design Summary Table
| Principle | Implementation Detail | Benefit |
|---|---|---|
| Zero-Assumption Serialization | Byte-oriented interfaces (&[u8]) README.md62 | Use bitcode, bincode, or manual encoding README.md:64-65 |
| Type Safety | rpc_method_id! macro & shared crates README.md:40-41 | Deterministic u64 IDs with zero runtime cost. |
| Multiplexing | stream_id in Frame header README.md:44-45 | Many concurrent streams over one unified connection. |
| Portability | RpcServiceCallerInterface trait README.md60 | Same application code works over WS, IPC, or WASM. |
| Flexibility | Layered Transport Kit DRAFT.md3 | Decouples high-level RPC from low-level I/O. |
| Efficiency | Compact Binary Protocol README.md:44-45 | 17 bytes overhead vs HTTP/2’s 9 bytes + gRPC headers. |
Sources:
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
RPC Layer: Dispatcher, Sessions & Stream Lifecycle
Loading…
RPC Layer: Dispatcher, Sessions & Stream Lifecycle
Relevant source files
- core/Cargo.toml
- core/src/rpc/rpc_dispatcher.rs
- core/src/rpc/rpc_internals.rs
- core/src/rpc/rpc_internals/README.md
- core/src/rpc/rpc_internals/rpc_header.rs
- core/src/rpc/rpc_internals/rpc_message_type.rs
- core/src/rpc/rpc_internals/rpc_respondable_session.rs
- core/src/rpc/rpc_internals/rpc_session.rs
- core/src/rpc/rpc_internals/rpc_stream_decoder.rs
- core/src/rpc/rpc_internals/rpc_stream_encoder.rs
- core/src/rpc/rpc_internals/rpc_stream_event.rs
- core/src/rpc/rpc_internals/rpc_trait.rs
- core/src/rpc/rpc_request_response.rs
- core/src/utils.rs
- core/src/utils/increment_u32_id.rs
- core/src/utils/now.rs
- extensions/muxio-ext-test/src/endpoint_helpers.rs
The RPC layer provides a high-level multiplexing engine on top of the binary frame protocol. It handles request correlation, stream-based payload delivery, and session management. It is designed to be runtime-agnostic, supporting both standard multithreaded environments and single-threaded WASM targets through a callback-driven, non-async model.
1. RPC Message Fundamentals
At the core of the RPC layer are structured messages that wrap raw byte streams with intent and identity.
- RpcHeader : Contains the essential routing information:
rpc_msg_type(Call, Response, or Event),rpc_request_id(correlation ID),rpc_method_id(function identifier), andrpc_metadata_bytescore/src/rpc/rpc_internals/rpc_header.rs:5-24 - RpcMessageType : An enum defining the nature of the message (e.g.,
Callfor requests,Responsefor replies) core/src/rpc/rpc_internals/rpc_message_type.rs:1-7 - RpcRequest / RpcResponse : High-level structures used by the
RpcDispatcherto manage outbound calls and inbound replies.RpcRequestincludes anis_finalizedflag to indicate if the payload is complete core/src/rpc/rpc_request_response.rs:10-33RpcResponsecan be constructed from anRpcHeaderusingfrom_rpc_header, extracting the result status from the first byte of metadata core/src/rpc/rpc_request_response.rs:90-104
Sources: core/src/rpc/rpc_internals/rpc_header.rs:5-24 core/src/rpc/rpc_request_response.rs:10-33 core/src/rpc/rpc_request_response.rs:90-104 core/src/rpc/rpc_internals/rpc_message_type.rs:1-7
2. Stream Lifecycle and Multiplexing
The RpcSession manages the low-level mechanics of mapping RPC messages to multiplexed streams.
Stream ID Allocation
Every RPC call initiates a new stream. RpcSession maintains a next_stream_id counter, initialized via increment_u32_id() core/src/rpc/rpc_internals/rpc_session.rs:21-33 This ensures that multiple concurrent RPC calls can coexist on a single transport without collision.
Data Flow: Encoding and Decoding
The session coordinates between the Frame layer and RPC events:
- Outbound :
init_requestcreates anRpcStreamEncoder, which wraps astream_idand anon_emitcallback core/src/rpc/rpc_internals/rpc_session.rs:35-50 - Inbound :
read_bytesfeeds raw data into aFrameMuxStreamDecodercore/src/rpc/rpc_internals/rpc_session.rs61 Decoded frames are then routed to a specificRpcStreamDecoderbased on theirstream_idcore/src/rpc/rpc_internals/rpc_session.rs:65-70 - Events : The
RpcStreamDecodertransitions through states (AwaitHeader->AwaitPayload->Done) core/src/rpc/rpc_internals/rpc_stream_decoder.rs:20-24 and emitsRpcStreamEventvariants:Header,PayloadChunk,End, orErrorcore/src/rpc/rpc_internals/rpc_stream_event.rs:6-29
Stream Termination
Streams are cleaned up from the rpc_stream_decoders map when an End or Cancel frame is received, or if a decoding error occurs core/src/rpc/rpc_internals/rpc_session.rs:73-101
Stream Lifecycle Diagram
Sources: core/src/rpc/rpc_internals/rpc_session.rs:20-117 core/src/rpc/rpc_internals/rpc_stream_decoder.rs:59-182 core/src/rpc/rpc_internals/rpc_stream_event.rs:6-29 core/src/rpc/rpc_internals/rpc_trait.rs:32-33
3. RpcRespondableSession: Handler Management
RpcRespondableSession is a wrapper that adds stateful response tracking to the base session. It maintains a map of response_handlers keyed by rpc_request_id core/src/rpc/rpc_internals/rpc_respondable_session.rs:21-28
- Pre-buffering : If
prebuffer_responseis enabled duringinit_respondable_request, the session accumulates allPayloadChunkevents into an internal buffer core/src/rpc/rpc_internals/rpc_respondable_session.rs:150-163 It executes the handler with a single aggregatedPayloadChunkonce theEndevent is received core/src/rpc/rpc_internals/rpc_respondable_session.rs:164-180 - Streaming Method Routing : It supports an optional
stream_method_routerthat can dynamically install per-request handlers for specific(method_id, request_id)pairs, allowing streaming handlers to bypass the standard catch-all logic core/src/rpc/rpc_internals/rpc_respondable_session.rs:97-102 - Catch-all Handler : A global fallback handler can be registered via
set_catch_all_response_handlerto process unsolicited messages or server-side requests core/src/rpc/rpc_internals/rpc_respondable_session.rs:106-111
Sources: core/src/rpc/rpc_internals/rpc_respondable_session.rs:21-45 core/src/rpc/rpc_internals/rpc_respondable_session.rs:97-102 core/src/rpc/rpc_internals/rpc_respondable_session.rs:113-180
4. RpcDispatcher: Request Correlation
The RpcDispatcher is the primary interface for application code. It manages a RpcRespondableSession and provides a synchronized queue for tracking inbound requests.
Internal Request Queue
The dispatcher installs a “catch-all” handler that populates an internal rpc_request_queue (a VecDeque of (u32, RpcRequest)) core/src/rpc/rpc_dispatcher.rs:50-51 This handler listens for incoming Header events to create new RpcRequest entries and appends PayloadChunk data to them as it arrives core/src/rpc/rpc_dispatcher.rs:118-162
Critical Safety
The rpc_request_queue is protected by a Mutex. If the mutex is poisoned, the dispatcher will panic! to prevent inconsistent state transitions or data loss core/src/rpc/rpc_dispatcher.rs:119-133
Entity Mapping: Code to Logic
Sources: core/src/rpc/rpc_dispatcher.rs:36-71 core/src/rpc/rpc_dispatcher.rs:114-162 core/src/rpc/rpc_internals/rpc_respondable_session.rs:21-33 core/src/rpc/rpc_internals/rpc_session.rs:20-24
5. Implementation Summary Table
| Component | Responsibility | File Reference |
|---|---|---|
RpcHeader | Binary layout of RPC metadata and IDs | core/src/rpc/rpc_internals/rpc_header.rs:5-24 |
RpcStreamEncoder | Fragments payloads into frames with headers | core/src/rpc/rpc_internals/rpc_stream_encoder.rs:6-12 |
RpcStreamDecoder | Reassembles frames into RpcStreamEvent | core/src/rpc/rpc_internals/rpc_stream_decoder.rs:11-18 |
RpcSession | Manages stream_id and decoder registry | core/src/rpc/rpc_internals/rpc_session.rs:20-24 |
RpcRespondableSession | Maps rpc_request_id to user callbacks and handles pre-buffering | core/src/rpc/rpc_internals/rpc_respondable_session.rs:21-33 |
RpcDispatcher | High-level correlation API and request queue | core/src/rpc/rpc_dispatcher.rs:36-51 |
Sources: core/src/rpc/rpc_internals/rpc_header.rs:5-24 core/src/rpc/rpc_internals/rpc_session.rs:20-33 core/src/rpc/rpc_dispatcher.rs:36-51 core/src/rpc/rpc_internals/rpc_respondable_session.rs:21-33
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
RPC Service Extension Layer
Loading…
RPC Service Extension Layer
Relevant source files
- extensions/muxio-rpc-service-caller/Cargo.toml
- extensions/muxio-rpc-service-endpoint/Cargo.toml
- extensions/muxio-rpc-service/Cargo.toml
The RPC Service Extension Layer provides high-level abstractions for defining, calling, and handling RPC services. While the core muxio crate handles the mechanics of binary framing and stream multiplexing, this layer introduces structured service definitions, client-side calling interfaces, and server-side handler registries.
These extensions are split into three primary crates to ensure a clear separation of concerns between shared definitions, client logic, and server logic.
Layered Architecture Overview
The following diagram illustrates how the RPC Service Extension crates sit between the low-level muxio core and the final transport implementations (like WebSocket or IPC).
Service Extension Topology
graph TD
subgraph "Application Space"
[ServiceDefinition] --> |implements| [RpcMethodPrebuffered]
end
subgraph "RPC Service Extension Layer"
[muxio-rpc-service-caller] -.-> [muxio-rpc-service]
[muxio-rpc-service-endpoint] -.-> [muxio-rpc-service]
end
subgraph "Muxio Core"
[muxio-rpc-service-caller] --> [RpcDispatcher]
[muxio-rpc-service-endpoint] --> [RpcRespondableSession]
end
[muxio-rpc-service-caller] --- [muxio-tokio-rpc-client]
[muxio-rpc-service-endpoint] --- [muxio-tokio-rpc-server]
Sources:
- extensions/muxio-rpc-service/Cargo.toml:1-3
- extensions/muxio-rpc-service-caller/Cargo.toml:1-3
- extensions/muxio-rpc-service-endpoint/Cargo.toml:1-3
muxio-rpc-service: Shared Service Definitions
The muxio-rpc-service crate defines the “language” that both clients and servers speak. It focuses on compile-time safety and efficient serialization using bitcode extensions/muxio-rpc-service/Cargo.toml12
- Trait-Based Definitions : Uses the
RpcMethodPrebufferedtrait to define RPC methods, associating them with specific request and response types. - Compile-Time Hashing : Provides the
rpc_method_id!macro, which usesxxhash-rustextensions/muxio-rpc-service/Cargo.toml14 at compile-time to generate uniqueu64identifiers for methods based on their names. - Standardized Results : Defines
RpcResultStatusandRpcServiceErrorto ensure consistent error propagation across the network. - Configuration : Sets the
DEFAULT_SERVICE_MAX_CHUNK_SIZEfor prebuffered message fragmentation.
For details, see muxio-rpc-service: Shared Service Definitions.
Sources:
muxio-rpc-service-caller: Client-Side Calling Interface
The muxio-rpc-service-caller crate provides the interface used by clients to initiate RPC requests. It abstracts the underlying RpcDispatcher into a more ergonomic API using async-trait extensions/muxio-rpc-service-caller/Cargo.toml12
- Caller Interface : The
RpcServiceCallerInterfacetrait defines how a client interacts with the transport, includingget_dispatcher,get_emit_fn, and checkingis_connectedstatus. - Typed Calling : Provides
call_rpc_bufferedandcall_rpc_streamingmethods that automatically handle serialization and deserialization based on theRpcMethodPrebuffereddefinition. - State Management : Tracks the
RpcTransportState(e.g., Connected, Disconnected) and allows applications to react to lifecycle events viaset_state_change_handler. - Dynamic Channels : Utilizes
DynamicChannel(Bounded or Unbounded) to manage asynchronous data flow for streaming calls, backed bytokio::syncextensions/muxio-rpc-service-caller/Cargo.toml16
For details, see muxio-rpc-service-caller: Client-Side Calling Interface.
Sources:
muxio-rpc-service-endpoint: Server-Side Handler Registry
The muxio-rpc-service-endpoint crate manages the server-side logic for receiving requests and routing them to the appropriate handlers.
- Handler Registration : The
RpcServiceEndpointstruct allows developers to register handlers for specific method IDs usingregister_prebuffered. - Execution Pipeline : Implements a three-stage
read_bytespipeline for incoming data:- Decode : Incoming bytes are decoded into the request type using
bitcodeextensions/muxio-rpc-service-endpoint/Cargo.toml17 - Execute : The registered
RpcPrebufferedHandleris executed (optionally concurrently). - Emit : The result is serialized and sent back to the client via the response emission logic.
- Decode : Incoming bytes are decoded into the request type using
- Concurrency : Includes support for
tokioto handle concurrent request processing via thetokio_supportfeature flag extensions/muxio-rpc-service-endpoint/Cargo.toml13 managing handlers through aHandlersLock.
For details, see muxio-rpc-service-endpoint: Server-Side Handler Registry.
Sources:
Entity Mapping: Extension to Core
The following table maps the high-level Extension Layer concepts to the low-level Core entities they wrap or utilize.
| Extension Entity | Core Entity | Role |
|---|---|---|
RpcServiceCallerInterface | RpcDispatcher | Wraps the dispatcher to provide type-safe call methods. |
RpcServiceEndpoint | RpcRespondableSession | Uses the session to read bytes and emit responses. |
RpcMethodPrebuffered | RpcHeader | Provides the u64 method ID stored in the header. |
DynamicChannel | Frame | Manages the flow of frames for streaming RPC calls. |
RpcResultStatus | RpcResponse | Encodes the success or failure status into the response header. |
Sources:
- extensions/muxio-rpc-service/Cargo.toml:12-14
- extensions/muxio-rpc-service-caller/Cargo.toml:14-16
- extensions/muxio-rpc-service-endpoint/Cargo.toml:20-23
Dismiss
Refresh this wiki
Enter email to refresh
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: Shared Service Definitions
Loading…
muxio-rpc-service: Shared Service Definitions
Relevant source files
- extensions/muxio-rpc-service/Cargo.toml
- extensions/muxio-rpc-service/README.md
- extensions/muxio-rpc-service/src/constants.rs
- extensions/muxio-rpc-service/src/macros.rs
- extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs
- extensions/muxio-rpc-service/src/result_status.rs
The muxio-rpc-service crate provides the foundational traits, constants, and macros required to define RPC service contracts within the Muxio framework extensions/muxio-rpc-service/Cargo.toml:2-3 It serves as the shared dependency between service providers (endpoints) and service consumers (callers), ensuring that both sides of a connection agree on method identifiers and serialization formats.
Core Service Abstractions
The crate centers around the “prebuffered” RPC model, where requests and responses are fully realized in memory before being processed or transmitted. This model simplifies service implementation by abstracting away the underlying stream-based transport.
RpcMethodPrebuffered Trait
The RpcMethodPrebuffered trait is the primary mechanism for defining a typed RPC method. It associates a unique u64 identifier with specific input and output types, along with their respective codec logic extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs:3-35
| Property | Description |
|---|---|
METHOD_ID | A unique u64 used by the RpcDispatcher to route requests to the correct handler extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs10 |
Input | The high-level Rust type for request data (e.g., a struct or Vec<f64>) extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs13 |
Output | The high-level Rust type for response data extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs16 |
encode_request | Serializes the Input type into a byte array for transport extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs19 |
decode_request | Deserializes raw bytes into the Input type on the server side extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs25 |
encode_response | Serializes the Output type into bytes after execution extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs28 |
decode_response | Deserializes raw bytes back into the Output type on the client side extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs34 |
Sources: extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs:3-35
Compile-Time Method Identification
To avoid manual management of magic numbers for method IDs, muxio-rpc-service provides a deterministic hashing mechanism.
rpc_method_id! Macro
The rpc_method_id! macro uses the xxh3 (64-bit) algorithm to generate method identifiers from string literals at compile time extensions/muxio-rpc-service/src/macros.rs:35-40
- Deterministic: Produces the same hash across all platforms, including WASM and native extensions/muxio-rpc-service/src/macros.rs14
- Zero Runtime Cost: The hash is computed during compilation via
method_id_hashand embedded as a constant extensions/muxio-rpc-service/src/macros.rs:3-5 extensions/muxio-rpc-service/src/macros.rs:37-38 - Collision Resistant: Uses
xxhash-rust(specificallyconst_xxh3_64) to provide stable identifiers for RPC routing extensions/muxio-rpc-service/src/macros.rs1 extensions/muxio-rpc-service/src/macros.rs:17-21
Sources: extensions/muxio-rpc-service/src/macros.rs:1-40
Response Status Mapping
The crate defines the status of an RPC execution through the RpcResultStatus enum, which is used to communicate the outcome of a request across the wire.
RpcResultStatus Enum
This enum is represented as a u8 for efficient transport and categorizes the result of an RPC call extensions/muxio-rpc-service/src/result_status.rs:3-10:
Success(0): The method executed successfully extensions/muxio-rpc-service/src/result_status.rs6Fail(1): Application-level failure (e.g., validation error) extensions/muxio-rpc-service/src/result_status.rs7SystemError(2): Internal framework or server error extensions/muxio-rpc-service/src/result_status.rs8MethodNotFound(3): The requestedMETHOD_IDis not registered on the endpoint extensions/muxio-rpc-service/src/result_status.rs9
Sources: extensions/muxio-rpc-service/src/result_status.rs:1-11
Constants and Configuration
Default values for transport and buffering are defined here to ensure consistency across implementations.
DEFAULT_SERVICE_MAX_CHUNK_SIZE: Set to 64KB (65,536 bytes), defining the standard upper bound for RPC payload chunks extensions/muxio-rpc-service/src/constants.rs19DEFAULT_RPC_STREAM_CHANNEL_BUFFER_SIZE: Set to 8 items. This controls the MPSC channel depth for streaming RPC calls, balancing memory usage against network jitter absorption extensions/muxio-rpc-service/src/constants.rs32
Sources: extensions/muxio-rpc-service/src/constants.rs:1-33
Architecture & Data Flow Diagrams
RPC Service Definition Logic
This diagram illustrates how the RpcMethodPrebuffered trait bridges high-level types to the binary transport using the rpc_method_id! macro.
Sources: extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs:3-35 extensions/muxio-rpc-service/src/macros.rs:35-40
graph TD
subgraph "Service Definition Space"
A["RpcMethodPrebuffered Trait"]
B["METHOD_ID"]
M["rpc_method_id! Macro"]
end
subgraph "Data Entities"
I["Input Type"]
O["Output Type"]
end
subgraph "Codec Logic"
E1["encode_request(Input) -> Vec<u8>"]
D1["decode_request(&[u8]) -> Input"]
E2["encode_response(Output) -> Vec<u8>"]
D2["decode_response(&[u8]) -> Output"]
end
M -- "Compile-time Hash" --> B
A --> B
A --> I
A --> O
I --> E1
E1 -.-> D1
O --> E2
E2 -.-> D2
graph LR
subgraph "Endpoint Execution"
EXEC["Handler Execution"]
SUCCESS["Success (0)"]
APP_ERR["Fail (1)"]
SYS_ERR["SystemError (2)"]
NOT_FOUND["MethodNotFound (3)"]
end
subgraph "Wire Representation"
STATUS["RpcResultStatus (u8)"]
end
subgraph "Caller Resolution"
RES["Result<Output, Error>"]
end
EXEC --> SUCCESS
EXEC --> APP_ERR
EXEC --> SYS_ERR
EXEC --> NOT_FOUND
SUCCESS --> STATUS
APP_ERR --> STATUS
SYS_ERR --> STATUS
NOT_FOUND --> STATUS
STATUS --> RES
Result Status Propagation
This diagram maps how RpcResultStatus categorizes the outcome of a service execution for the caller.
Sources: extensions/muxio-rpc-service/src/result_status.rs:3-10
Module Structure
The crate is organized into several modules to separate concerns:
prebuffered: Contains the coreRpcMethodPrebufferedtrait definition extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs:3-35constants: Global defaults for chunk sizes and buffer depths extensions/muxio-rpc-service/src/constants.rs:1-33macros: Contains themethod_id_hashfunction and therpc_method_id!macro extensions/muxio-rpc-service/src/macros.rs:1-40result_status: Defines theRpcResultStatusenum for cross-wire error reporting extensions/muxio-rpc-service/src/result_status.rs:1-11
Sources: extensions/muxio-rpc-service/src/constants.rs:1-33 extensions/muxio-rpc-service/src/macros.rs:1-40 extensions/muxio-rpc-service/src/result_status.rs:1-11 extensions/muxio-rpc-service/src/prebuffered/prebuffered_traits.rs:3-35
Dismiss
Refresh this wiki
Enter email to refresh
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-caller: Client-Side Calling Interface
Loading…
muxio-rpc-service-caller: Client-Side Calling Interface
Relevant source files
- extensions/muxio-rpc-service-caller/Cargo.toml
- extensions/muxio-rpc-service-caller/README.md
- extensions/muxio-rpc-service-caller/src/caller_interface.rs
- extensions/muxio-rpc-service-caller/src/dynamic_channel.rs
- extensions/muxio-rpc-service-caller/src/transport_state.rs
- extensions/muxio-rpc-service-caller/src/write_channel.rs
- extensions/muxio-rpc-service-endpoint/README.md
- extensions/muxio-tokio-rpc-server/src/rpc_server.rs
The muxio-rpc-service-caller crate provides a high-level, runtime-agnostic interface for building Muxio RPC clients extensions/muxio-rpc-service-caller/Cargo.toml:2-3 It abstracts the complexities of stream lifecycle management, request correlation, and payload chunking into a simplified calling API.
RpcServiceCallerInterface
The core of the client-side logic is the RpcServiceCallerInterface trait. It defines the minimum set of capabilities a transport (like Tokio or WASM) must provide to support RPC calls extensions/muxio-rpc-service-caller/src/caller_interface.rs:25-31
Key Methods
| Method | Description |
|---|---|
get_dispatcher | Returns the Arc<TokioMutex<RpcDispatcher>> used for request correlation extensions/muxio-rpc-service-caller/src/caller_interface.rs28 |
get_emit_fn | Returns a function used to send raw bytes to the underlying transport extensions/muxio-rpc-service-caller/src/caller_interface.rs29 |
is_connected | Checks the current connectivity status extensions/muxio-rpc-service-caller/src/caller_interface.rs30 |
set_state_change_handler | Registers a callback for transport state transitions extensions/muxio-rpc-service-caller/src/caller_interface.rs:226-229 |
call_rpc_streaming | Initiates an RPC call and returns an encoder and a response stream extensions/muxio-rpc-service-caller/src/caller_interface.rs:33-43 |
call_rpc_buffered | A convenience method that buffers the entire response before returning extensions/muxio-rpc-service-caller/src/caller_interface.rs:189-195 |
RPC Call Data Flow
The following diagram illustrates how a call moves from the high-level interface through the dispatcher to the transport.
Client-Side Call Flow
sequenceDiagram
participant User as "User Code"
participant Caller as "RpcServiceCallerInterface"
participant Disp as "RpcDispatcher"
participant Trans as "Transport (Emit)"
User->>Caller: call_rpc_streaming(RpcRequest)
Caller->>Disp: register_session()
Disp-->>Caller: RpcSession (StreamID)
Caller->>Trans: emit(HeaderFrame)
Caller-->>User: (RpcStreamEncoder, DynamicReceiver)
Note over User, Trans: Data Streaming Phase
User->>Caller: encoder.write_payload(chunk)
Caller->>Trans: emit(PayloadFrame)
Trans-->>Caller: recv_fn(RpcStreamEvent)
Caller->>User: DynamicReceiver.next()
Sources: extensions/muxio-rpc-service-caller/src/caller_interface.rs:33-187 extensions/muxio-rpc-service-caller/src/caller_interface.rs:189-224
Dynamic Channels
To handle asynchronous responses, the caller uses DynamicChannel, which provides a unified interface over both bounded and unbounded futures::channel::mpsc channels extensions/muxio-rpc-service-caller/src/dynamic_channel.rs:11-16
DynamicSender: WrapsSenderorUnboundedSender. It includes asend_and_ignoremethod that handles channel errors gracefully (e.g., if the caller dropped the receiver) extensions/muxio-rpc-service-caller/src/dynamic_channel.rs:21-45DynamicReceiver: Implements theStreamtrait, allowing users to consume response chunks viawhile let Some(...) = stream.next().awaitextensions/muxio-rpc-service-caller/src/dynamic_channel.rs:48-75
Sources: extensions/muxio-rpc-service-caller/src/dynamic_channel.rs:1-76
RpcCallPrebuffered Blanket Implementation
The RpcCallPrebuffered trait provides a “smart” transport strategy for RPC methods defined using the RpcMethodPrebuffered pattern extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs:11-21
Smart Transport Strategy
Because a single Muxio frame header is limited (typically ~64KB), the implementation automatically decides how to send arguments:
- Small Arguments : If the encoded input is smaller than
DEFAULT_SERVICE_MAX_CHUNK_SIZE, it is sent inside therpc_param_bytesfield of the initial header frame extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs:63-65 - Large Arguments : If the input is large, it is placed in
rpc_prebuffered_payload_bytes. TheRpcDispatcherthen automatically chunks and streams this data as subsequent payload frames extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs:59-61
Entity Mapping: Prebuffered Call
Sources: extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs:30-74 extensions/muxio-rpc-service-caller/src/caller_interface.rs:189-200
Write Loop and Backpressure
The write_channel module provides spawn_write_loop, which manages the outbound message queue for a connection extensions/muxio-rpc-service-caller/src/write_channel.rs:34-41
- Unbounded Channel : Uses an
mpsc::unbounded_channelto prevent blocking the synchronouswrite_bytescall in the framing layer extensions/muxio-rpc-service-caller/src/write_channel.rs:9-16 - Stall Prevention : By using an unbounded channel at the connection level, the system ensures that a slow stream does not immediately block all other streams sharing the same physical transport extensions/muxio-rpc-service-caller/src/write_channel.rs:11-16
Sources: extensions/muxio-rpc-service-caller/src/write_channel.rs:1-54
Transport State and Error Handling
RpcTransportState
The client tracks the connection status using the RpcTransportState enum:
Connected: Transport is active and ready for calls extensions/muxio-rpc-service-caller/src/transport_state.rs3Disconnected: Transport is closed; new calls will be rejected immediately extensions/muxio-rpc-service-caller/src/transport_state.rs4Connecting: Transport is establishing a connection extensions/muxio-rpc-service-caller/src/transport_state.rs5
Error Handling
Errors are encapsulated in the RpcServiceError type.
- Immediate Rejection : If
is_connected()is false,call_rpc_streamingreturnsio::ErrorKind::ConnectionAbortedextensions/muxio-rpc-service-caller/src/caller_interface.rs:44-53 - Remote Errors : If the server returns an error status (e.g.,
Fail,System), the caller collects the error payload from the stream and returns it as anRpcServiceError::Rpcextensions/muxio-rpc-service-caller/src/caller_interface.rs:152-164 - Decoding Errors : Failures during the deserialization of the response are returned as
RpcServiceError::Transportwrapping anio::Errorextensions/muxio-rpc-service-caller/src/prebuffered/traits.rs90
Entity Mapping: Error Propagation
Sources: extensions/muxio-rpc-service-caller/src/transport_state.rs:1-7 extensions/muxio-rpc-service-caller/src/caller_interface.rs:44-53 extensions/muxio-rpc-service-caller/src/caller_interface.rs:118-170 extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs90
Dismiss
Refresh this wiki
Enter email to refresh
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
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Transport Implementations
Loading…
Transport Implementations
Relevant source files
- extensions/muxio-tokio-rpc-client/Cargo.toml
- extensions/muxio-tokio-rpc-ipc-client/Cargo.toml
- extensions/muxio-tokio-rpc-server/Cargo.toml
- extensions/muxio-wasm-rpc-client/Cargo.toml
The Transport Implementation layer consists of concrete crates that bridge the high-level RPC service abstractions to physical network I/O. While the core muxio crate and the muxio-rpc-service-* extensions handle framing and dispatching logic, these transport crates manage the lifecycle of actual connections, such as WebSocket streams over TCP, Unix Domain Sockets, or browser-based sockets.
Architecture Overview
Muxio provides several transport implementations designed for different runtime environments and communication patterns:
muxio-tokio-rpc-server: A native Rust server built on the Tokio runtime andtokio-tungstenite[extensions/muxio-tokio-rpc-server/Cargo.toml:1-22].muxio-tokio-rpc-client: A native Rust client for desktop or server-to-server communication usingtokio-tungstenite[extensions/muxio-tokio-rpc-client/Cargo.toml:1-22].muxio-wasm-rpc-client: A specialized client for web browsers, utilizingwasm-bindgento interface with JavaScript-managed sockets [extensions/muxio-wasm-rpc-client/Cargo.toml:1-22].- IPC Transports : Specialized crates for local inter-process communication using
interprocessfor Unix domain sockets and Windows named pipes [extensions/muxio-tokio-rpc-ipc-client/Cargo.toml:1-22].
graph TD
subgraph "Application Code"
[ServiceDefinition]
end
subgraph "Transport Layer (Code Entities)"
Server["RpcServer (muxio-tokio-rpc-server)"]
NativeClient["RpcClient (muxio-tokio-rpc-client)"]
WasmClient["RpcWasmClient (muxio-wasm-rpc-client)"]
IpcClient["RpcIpcClient (muxio-tokio-rpc-ipc-client)"]
end
subgraph "Core & Service Layer"
Endpoint["RpcServiceEndpoint"]
Dispatcher["RpcDispatcher"]
end
Server --> Endpoint
NativeClient --> Dispatcher
WasmClient --> Dispatcher
IpcClient --> Dispatcher
[ServiceDefinition] -. "implements" .-> Endpoint
[ServiceDefinition] -. "calls via" .-> NativeClient
[ServiceDefinition] -. "calls via" .-> WasmClient
[ServiceDefinition] -. "calls via" .-> IpcClient
The following diagram illustrates how these transports connect the RpcDispatcher to the network:
Transport Entity Map
Sources: [extensions/muxio-tokio-rpc-server/Cargo.toml:1-22], [extensions/muxio-tokio-rpc-client/Cargo.toml:1-22], [extensions/muxio-wasm-rpc-client/Cargo.toml:1-22], [extensions/muxio-tokio-rpc-ipc-client/Cargo.toml:1-22].
muxio-tokio-rpc-server: WebSocket RPC Server
The muxio-tokio-rpc-server crate provides the RpcServer struct, which manages incoming WebSocket connections. It is responsible for hosting an RpcServiceEndpoint and spawning asynchronous tasks to handle each connected client [extensions/muxio-tokio-rpc-server/Cargo.toml:11-22].
- Bidirectional Calling : Unlike traditional REST servers, the
RpcServercan initiate calls back to connected clients using theConnectionContextHandle. - Heartbeat Mechanism : Implements
HEARTBEAT_INTERVALandCLIENT_TIMEOUTlogic to prune dead connections. - Task Architecture : Each connection spawns a
sender_taskand areceiver_taskto ensure full-duplex communication without head-of-line blocking at the application level.
For details on server configuration and connection management, see muxio-tokio-rpc-server: WebSocket RPC Server.
Sources: [extensions/muxio-tokio-rpc-server/Cargo.toml:1-22].
muxio-tokio-rpc-client: Native Async RPC Client
The muxio-tokio-rpc-client crate provides the RpcClient, a native Rust implementation of the RpcServiceCallerInterface. It is designed for high-performance, asynchronous environments using the Tokio runtime [extensions/muxio-tokio-rpc-client/Cargo.toml:11-22].
- Three-Task Architecture : Internally manages three concurrent loops: a heartbeat loop, a receive loop for incoming frames/responses, and a send loop for outgoing requests.
- State Management : Tracks
RpcTransportStateand allows users to set state change handlers to react to disconnections. - Graceful Shutdown : Supports both
shutdown_asyncandshutdown_syncto ensure pending requests are handled or cancelled before the client is dropped.
For details on the native client’s task lifecycle and state transitions, see muxio-tokio-rpc-client: Native Async RPC Client.
Sources: [extensions/muxio-tokio-rpc-client/Cargo.toml:1-22].
muxio-wasm-rpc-client: Browser/WASM RPC Client
The muxio-wasm-rpc-client crate is a specialized implementation of the Muxio protocol for WebAssembly targets. Because browsers do not allow raw TCP access, this crate facilitates communication through a JavaScript bridge [extensions/muxio-wasm-rpc-client/Cargo.toml:14-22].
- JS Bridge : Uses
wasm-bindgento export functions likestatic_muxio_write_bytes_uint8andstatic_muxio_read_bytes_uint8, allowing a JavaScript-based WebSocket to pass data into the Rust RPC engine. - Static Client Pattern : Provides
MUXIO_STATIC_RPC_CLIENT_REFandinit_static_clientto manage a global RPC singleton, which is a common requirement in WASM applications where ownership across the JS/Rust boundary is complex. - Lifecycle : Manages the
handle_connectandhandle_disconnectevents triggered by the browser’s networking stack.
For details on the WASM-to-JS integration and static client usage, see muxio-wasm-rpc-client: Browser/WASM RPC Client.
Sources: [extensions/muxio-wasm-rpc-client/Cargo.toml:1-22].
IPC Transports & MPSC Adapter
Muxio supports local communication via IPC and internal channels:
- IPC Transports : The
muxio-tokio-rpc-ipc-clientandmuxio-tokio-rpc-ipc-servercrates useinterprocessto provide high-speed local communication over Unix Domain Sockets or Windows Named Pipes [extensions/muxio-tokio-rpc-ipc-client/Cargo.toml:1-22]. - MPSC Adapter : The
muxio-tokio-mpsc-adaptercrate allows using standard Rust MPSC channels as a transport, which is useful for internal service communication within a single process or for testing purposes.
For details on local transports and streaming adapters, see IPC Transports & MPSC Adapter.
Sources: [extensions/muxio-tokio-rpc-ipc-client/Cargo.toml:1-22].
Transport Interaction Lifecycle
The following diagram demonstrates the typical flow of data from a high-level RPC call through a transport implementation to the network.
sequenceDiagram
participant App as "Application Code"
participant Caller as "RpcServiceCallerInterface"
participant Transport as "RpcClient / RpcWasmClient"
participant Dispatcher as "RpcDispatcher"
participant Network as "Network I/O (WebSocket/TCP)"
App->>Caller: call_rpc_buffered(method, args)
Caller->>Dispatcher: call(request_bytes)
Dispatcher->>Transport: emit_fn(frame_bytes)
Note over Transport: Transport Task (Send Loop)
Transport->>Network: Send Binary Frame
Network-->>Transport: Receive Binary Frame
Transport->>Dispatcher: read_bytes(frame_bytes)
Dispatcher-->>App: Return RpcResult
Data Flow: Caller to Transport
Sources: [extensions/muxio-tokio-rpc-client/Cargo.toml:16-19], [extensions/muxio-wasm-rpc-client/Cargo.toml:15-18].
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
muxio-tokio-rpc-server: WebSocket RPC Server
Loading…
muxio-tokio-rpc-server: WebSocket RPC Server
Relevant source files
- extensions/muxio-rpc-service-caller/src/caller_interface.rs
- extensions/muxio-tokio-rpc-server/Cargo.toml
- extensions/muxio-tokio-rpc-server/README.md
- extensions/muxio-tokio-rpc-server/src/lib.rs
- extensions/muxio-tokio-rpc-server/src/rpc_server.rs
- extensions/muxio-wasm-rpc-client/src/static_lib/static_transport_bridge.rs
The muxio-tokio-rpc-server crate provides a reference implementation of a Muxio RPC server using the Tokio runtime, Axum web framework, and WebSockets (via tokio-tungstenite). It enables high-performance, bidirectional RPC communication where the server can both handle requests from clients and initiate calls back to connected clients extensions/muxio-tokio-rpc-server/src/rpc_server.rs:1-6
Core Architecture
The server is built around the RpcServer struct, which manages an RpcServiceEndpoint for request dispatching and handles the lifecycle of WebSocket connections. Each connection is managed by two primary asynchronous tasks: a sender_task and a receiver_task extensions/muxio-tokio-rpc-server/src/rpc_server.rs:66-69 extensions/muxio-tokio-rpc-server/src/rpc_server.rs:183-191
Server-to-Code Entity Mapping
The following diagram illustrates how high-level server concepts map to specific structs and functions in the codebase.
Entity Relationship Diagram
graph TD
subgraph "muxio-tokio-rpc-server"
RpcServer["RpcServer (struct)"]
ConnectionContext["ConnectionContext (struct)"]
ConnectionContextHandle["ConnectionContextHandle (newtype)"]
WsSenderContext["WsSenderContext (type alias)"]
RpcServer -- "owns" --> RpcServiceEndpoint["RpcServiceEndpoint (from muxio-rpc-service-endpoint)"]
RpcServer -- "spawns" --> receiver_task["RpcServer::receiver_task (fn)"]
ConnectionContext -- "contains" --> RpcDispatcher["RpcDispatcher (from muxio-core)"]
ConnectionContext -- "contains" --> WsSenderContext
ConnectionContextHandle -- "wraps" --> ConnectionContext
end
subgraph "External Dependencies"
AxumRouter["axum::Router"]
TcpListener["tokio::net::TcpListener"]
end
RpcServer -- "configures" --> AxumRouter
RpcServer -- "binds" --> TcpListener
Sources: extensions/muxio-tokio-rpc-server/src/rpc_server.rs:48-69 extensions/muxio-tokio-rpc-server/src/rpc_server.rs:183-191
Key Components
RpcServer
The RpcServer is the entry point for starting the service. It allows for registering RPC handlers via its internal endpoint and provides methods for binding to network interfaces.
new(event_tx): Initializes the server. It can optionally take anmpsc::UnboundedSender<RpcServerEvent>to notify the application when clients connect or disconnect extensions/muxio-tokio-rpc-server/src/rpc_server.rs:77-82endpoint(): Provides access to theRpcServiceEndpoint, allowing the registration ofRpcMethodPrebufferedhandlers extensions/muxio-tokio-rpc-server/src/rpc_server.rs:85-87serve(addr)/serve_with_listener(listener): Starts the Axum-based web server. It routes WebSocket upgrades to the/wsendpoint extensions/muxio-tokio-rpc-server/src/rpc_server.rs:90-122
Connection Management
Every client connection is represented by a ConnectionContext. Because the server supports bidirectional calling, each connection maintains its own RpcDispatcher extensions/muxio-tokio-rpc-server/src/rpc_server.rs54
ConnectionContextHandle: A wrapper aroundArc<ConnectionContext>used to implementRpcServiceCallerInterface, enabling the server to call methods on the client extensions/muxio-tokio-rpc-server/src/rpc_server.rs:57-60RpcServerEvent: An enum used to signal connection lifecycle changes:ClientConnected(ConnectionContextHandle)extensions/muxio-tokio-rpc-server/src/rpc_server.rs44ClientDisconnected(SocketAddr)extensions/muxio-tokio-rpc-server/src/rpc_server.rs45
Data Flow & Task Architecture
The server utilizes a split-task architecture for every WebSocket connection to ensure full-duplex communication and independent heartbeat monitoring.
Connection Data Flow
sequenceDiagram
participant Peer as "Remote Client"
participant RX as "receiver_task"
participant EP as "RpcServiceEndpoint"
participant TX as "spawn_write_loop"
participant MPSC as "Internal MPSC Channel"
Note over RX, TX: Per-Connection Tasks
Peer->>RX: WebSocket Message (Binary)
RX->>EP: read_bytes(dispatcher, context, bytes, on_emit)
EP->>EP: Stage 1: Decode & Identify
EP->>EP: Stage 2: Concurrent Execute Handlers
EP->>EP: Stage 3: Encode & Emit
EP-->>MPSC: Response Frames
MPSC->>TX: Internal Message
TX->>Peer: WebSocket Message (Binary)
loop Heartbeat
RX->>Peer: Ping (Every 5s)
Peer-->>RX: Pong
end
Sources: extensions/muxio-tokio-rpc-server/src/rpc_server.rs:183-191 extensions/muxio-tokio-rpc-server/src/rpc_server.rs:35-40 extensions/muxio-rpc-service-caller/src/caller_interface.rs:123-163
sender_task (via spawn_write_loop)
The server uses muxio_rpc_service_caller::write_channel::spawn_write_loop to manage outgoing data extensions/muxio-tokio-rpc-server/src/rpc_server.rs:157-164
- Egress : It listens to an internal
mpscchannel for messages generated by RPC handlers or server-initiated calls and forwards them to theWsSenderContextextensions/muxio-tokio-rpc-server/src/rpc_server.rs:49-51 extensions/muxio-tokio-rpc-server/src/rpc_server.rs:157-167
receiver_task & Heartbeats
The receiver_task processes incoming data and manages connection liveness:
- Heartbeat Mechanism : It monitors the connection and expects activity. While the
receiver_tasklogic includes aCLIENT_TIMEOUT(15 seconds), it typically works in tandem with pings sent atHEARTBEAT_INTERVAL(5 seconds) extensions/muxio-tokio-rpc-server/src/rpc_server.rs:35-40 - Message Dispatch : It receives WebSocket messages from the client. Binary data is passed to the
RpcServiceEndpointInterface::read_bytesmethod extensions/muxio-tokio-rpc-server/src/rpc_server.rs23 extensions/muxio-tokio-rpc-server/src/rpc_server.rs:183-191 - Three-Stage Pipeline :
read_bytesimplements a three-stage pipeline:- Decode : Incoming frames are decoded and finalized requests identified.
- Execute : Handlers are executed concurrently for all finalized requests.
- Emit : Responses are encoded and emitted back to the transport.
- Timeouts : If no message (including
Pong) is received withinCLIENT_TIMEOUT, the connection is considered dead and closed extensions/muxio-tokio-rpc-server/src/rpc_server.rs:38-40
Utility Functions
The crate includes utilities for managing TCP listeners, primarily used in testing or dynamic environment setups:
| Function | Description |
|---|---|
bind_tcp_listener_on_random_port | Binds a TcpListener to 127.0.0.1:0 and returns the listener plus the OS-assigned port extensions/muxio-tokio-rpc-server/src/utils/mod.rs |
tcp_listener_to_host_port | Extracts the IpAddr and u16 port from an existing TcpListener extensions/muxio-tokio-rpc-server/src/utils/mod.rs |
Sources: extensions/muxio-tokio-rpc-server/src/lib.rs5 extensions/muxio-tokio-rpc-server/src/rpc_server.rs:1-200
Implementation Notes
- No Auth : The reference implementation does not include built-in authentication. Users should implement a custom
AuthHookwithin thews_handlerbefore callingws.on_upgradeextensions/muxio-tokio-rpc-server/src/rpc_server.rs:1-6 extensions/muxio-tokio-rpc-server/src/rpc_server.rs:130-147 - Concurrency : Request handling is concurrent. The
RpcServiceEndpointprocesses incoming RPC frames and can execute multiple handlers in parallel, piping results back through the connection’s sender channel extensions/muxio-tokio-rpc-server/src/rpc_server.rs:183-191 - Bidirectional Capability : By implementing
RpcServiceCallerInterfaceonConnectionContextHandle, the server can use thedispatcherinside theConnectionContextto initiate calls to the client extensions/muxio-tokio-rpc-server/src/rpc_server.rs:54-60
Sources: extensions/muxio-tokio-rpc-server/src/rpc_server.rs:1-200 extensions/muxio-rpc-service-caller/src/caller_interface.rs:25-53
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
muxio-tokio-rpc-client: Native Async RPC Client
Loading…
muxio-tokio-rpc-client: Native Async RPC Client
Relevant source files
- extensions/muxio-rpc-service-caller/src/lib.rs
- extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs
- extensions/muxio-rpc-service-caller/tests/dynamic_channel_tests.rs
- extensions/muxio-tokio-rpc-client/Cargo.toml
- extensions/muxio-tokio-rpc-client/README.md
- extensions/muxio-tokio-rpc-client/src/lib.rs
- extensions/muxio-tokio-rpc-client/src/rpc_client.rs
- extensions/muxio-tokio-rpc-client/tests/ping_tests.rs
- extensions/muxio-wasm-rpc-client/src/lib.rs
- extensions/muxio-wasm-rpc-client/src/static_lib/static_client.rs
The muxio-tokio-rpc-client crate provides a high-performance, asynchronous RPC client implementation for native environments using the Tokio runtime and tungstenite for WebSocket transport extensions/muxio-tokio-rpc-client/Cargo.toml:15-21 It implements the RpcServiceCallerInterface to support both request-response and streaming RPC patterns extensions/muxio-tokio-rpc-client/src/rpc_client.rs232
The RpcClient Struct
The RpcClient is the primary entry point for client-side operations. It manages the lifecycle of the connection, handles heartbeats, and coordinates between the low-level RpcDispatcher and the high-level RpcServiceEndpoint extensions/muxio-tokio-rpc-client/src/rpc_client.rs:25-32
Key Components
| Component | Type | Role |
|---|---|---|
dispatcher | Arc<TokioMutex<RpcDispatcher>> | Manages RPC session IDs and correlates responses to requests extensions/muxio-tokio-rpc-client/src/rpc_client.rs26 |
endpoint | Arc<RpcServiceEndpoint<()>> | Registry for handlers if the server initiates calls to this client extensions/muxio-tokio-rpc-client/src/rpc_client.rs27 |
tx | mpsc::UnboundedSender<WsMessage> | Channel for sending WebSocket messages to the network task extensions/muxio-tokio-rpc-client/src/rpc_client.rs28 |
is_connected | Arc<AtomicBool> | Thread-safe flag indicating the current transport health extensions/muxio-tokio-rpc-client/src/rpc_client.rs30 |
task_handles | Vec<JoinHandle<()>> | Handles for the three background tasks (Heartbeat, Receive loop, Send loop) extensions/muxio-tokio-rpc-client/src/rpc_client.rs31 |
Sources: extensions/muxio-tokio-rpc-client/src/rpc_client.rs:25-40
Three-Task Architecture
When a new RpcClient is initialized via RpcClient::new(host, port), it establishes a WebSocket connection and spawns three distinct Tokio tasks to manage full-duplex communication extensions/muxio-tokio-rpc-client/src/rpc_client.rs:111-155
Task Interaction Diagram
This diagram illustrates how the internal tasks interact with the WebSocket stream and the core RPC components.
Client Task Coordination
graph TD
subgraph "RpcClient_Internal_Tasks"
HBT["heartbeat_handle"]
RL["recv_handle"]
SL["send_handle"]
end
subgraph "Network_IO"
WS_S["ws_sender"]
WS_R["ws_receiver"]
end
subgraph "Core_Logic"
DISP["RpcDispatcher"]
ENDP["RpcServiceEndpoint"]
TX_CH["app_tx (MPSC)"]
end
HBT -- "WsMessage::Ping" --> TX_CH
TX_CH -- "app_rx.recv()" --> SL
SL -- "ws_sender.send()" --> WS_S
WS_R -- "ws_receiver.next()" --> RL
RL -- "dispatcher.read_bytes()" --> DISP
RL -- "endpoint.read_bytes()" --> ENDP
RL -- "Automatic Pong" --> TX_CH
Sources: extensions/muxio-tokio-rpc-client/src/rpc_client.rs:141-210
1. Heartbeat Task
The heartbeat task runs on a 1-second interval extensions/muxio-tokio-rpc-client/src/rpc_client.rs150 It sends a WsMessage::Ping to the server to maintain the connection and detect silent timeouts extensions/muxio-tokio-rpc-client/src/rpc_client.rs153
2. Receive Loop
The receive loop continuously polls the ws_receiver extensions/muxio-tokio-rpc-client/src/rpc_client.rs164
- Binary Messages : Passed to both the
dispatcher(for responses to client calls) and theendpoint(for server-initiated calls) extensions/muxio-tokio-rpc-client/src/rpc_client.rs:188-202 - Pings : The client automatically responds with a
Pongby sending it to the internaltxchannel extensions/muxio-tokio-rpc-client/src/rpc_client.rs:169-171 - Close/Error : Triggers the
shutdown_async()routine if the stream ends or errors extensions/muxio-tokio-rpc-client/src/rpc_client.rs:205-212
3. Send Loop
The send loop is managed via the muxio_rpc_service_caller::write_channel::spawn_write_loop utility extensions/muxio-tokio-rpc-client/src/rpc_client.rs:129-136 It pulls WsMessage items from the internal MPSC channel and flushes them to the network using the split ws_sender extensions/muxio-tokio-rpc-client/src/rpc_client.rs134
Connection Lifecycle & Shutdown
The RpcClient handles graceful and forced shutdowns to ensure no RPC requests are left hanging indefinitely.
Shutdown Mechanisms
shutdown_async(): Used internally when the receive loop detects a connection drop. It swaps theis_connectedflag, triggers the state change handler, and callsdispatcher.fail_all_pending_requests(FrameDecodeError::ReadAfterCancel)to resolve all pending futures with an error extensions/muxio-tokio-rpc-client/src/rpc_client.rs:80-108shutdown_sync(): A synchronous version used duringDropto notify handlers and update state without awaiting futures extensions/muxio-tokio-rpc-client/src/rpc_client.rs:56-77DropImplementation: When theRpcClientis dropped, it aborts all background tasks via theirJoinHandleand performs a synchronous shutdown extensions/muxio-tokio-rpc-client/src/rpc_client.rs:42-52
State Management
Users can monitor the connection status using is_connected() or by registering a callback via set_state_change_handler() extensions/muxio-tokio-rpc-client/src/rpc_client.rs:271-284 This handler receives RpcTransportState::Connected or Disconnected events extensions/muxio-rpc-service-caller/src/transport_state.rs:1-10
Sources: extensions/muxio-tokio-rpc-client/src/rpc_client.rs:42-108 extensions/muxio-tokio-rpc-client/src/rpc_client.rs:271-284
Implementation of RpcServiceCallerInterface
RpcClient implements the standard caller interface, allowing it to be used with high-level traits like RpcCallPrebuffered extensions/muxio-tokio-rpc-client/src/rpc_client.rs232
Entity Mapping: Interface to Implementation
Sources: extensions/muxio-tokio-rpc-client/src/rpc_client.rs:232-284 extensions/muxio-rpc-service-caller/src/caller_interface.rs:10-30
Call Flow
When call_rpc_streaming is invoked:
- It checks the
is_connectedatomic flag extensions/muxio-tokio-rpc-client/src/rpc_client.rs245 - It creates a
DynamicChannel(eitherBoundedorUnbounded) to receive the response stream extensions/muxio-tokio-rpc-client/src/rpc_client.rs247 - It locks the
RpcDispatcherto register the call and obtain anRpcStreamEncoderextensions/muxio-tokio-rpc-client/src/rpc_client.rs:249-253 - The encoder’s
on_emitclosure is configured to wrap chunks inWsMessage::Binaryand send them to the client’s internaltxchannel extensions/muxio-tokio-rpc-client/src/rpc_client.rs251
Sources: extensions/muxio-tokio-rpc-client/src/rpc_client.rs:232-255
Integration and Testing
The client is extensively tested for transport reliability and protocol correctness.
- Connection Failures : Validates that attempting to connect to a non-listening port returns
std::io::ErrorKind::ConnectionRefusedextensions/muxio-tokio-rpc-client/src/rpc_client.rs:118-121 - Heartbeat Logic :
test_client_responds_to_ping_with_pongensures the client’s receive loop correctly identifies WebSocket Pings and sends the corresponding Pongs automatically extensions/muxio-tokio-rpc-client/tests/ping_tests.rs:17-89 - Dynamic Channels : Tests ensure that
RpcClientcan handle both bounded and unbounded streaming responses correctly extensions/muxio-rpc-service-caller/tests/dynamic_channel_tests.rs:101-167 - Prebuffered Interface :
RpcCallPrebufferedprovides a blanket implementation that usesRpcClientto handle automatic chunking of large RPC arguments extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs:30-65
Sources: extensions/muxio-tokio-rpc-client/tests/ping_tests.rs:1-90 extensions/muxio-rpc-service-caller/tests/dynamic_channel_tests.rs:1-168 extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs:11-98
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
muxio-wasm-rpc-client: Browser/WASM RPC Client
Loading…
muxio-wasm-rpc-client: Browser/WASM RPC Client
Relevant source files
- extensions/muxio-rpc-service-endpoint/src/error.rs
- extensions/muxio-rpc-service-endpoint/src/lib.rs
- extensions/muxio-rpc-service-endpoint/tests/prebuffered_endpoint_tests.rs
- extensions/muxio-tokio-rpc-client/src/lib.rs
- extensions/muxio-tokio-rpc-server/src/lib.rs
- extensions/muxio-wasm-rpc-client/Cargo.toml
- extensions/muxio-wasm-rpc-client/README.md
- extensions/muxio-wasm-rpc-client/src/lib.rs
- extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs
- extensions/muxio-wasm-rpc-client/src/static_lib.rs
- extensions/muxio-wasm-rpc-client/src/static_lib/README.md
- extensions/muxio-wasm-rpc-client/src/static_lib/static_client.rs
- extensions/muxio-wasm-rpc-client/src/static_lib/static_transport_bridge.rs
The muxio-wasm-rpc-client crate provides a WebAssembly-compatible implementation of the Muxio RPC client. It is designed to run in browser environments or any WASM runtime that provides a JavaScript bridge for network I/O. Unlike the native Tokio client, which manages its own sockets via background tasks, this client relies on external triggers (typically from JavaScript) to drive its internal state and data processing.
RpcWasmClient Architecture
The RpcWasmClient acts as the central coordinator for WASM-based RPC operations. It integrates a RpcDispatcher for managing outgoing calls and an RpcServiceEndpoint for handling incoming requests from the remote peer extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:14-21
Key Components
| Component | Role |
|---|---|
dispatcher | Manages RPC stream allocation, request correlation, and frame encoding/decoding extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs15 |
endpoint | Registry for handlers that process incoming RPC calls from the host/server extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs17 |
emit_callback | A closure used to send serialized binary chunks back to the JavaScript environment for network transmission extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs18 |
is_connected | An AtomicBool tracking the transport state extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs20 |
Entity Mapping: Client Internals
The following diagram shows how the RpcWasmClient struct maps to the core Muxio entities.
graph TD
subgraph "RpcWasmClient [extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs]"
C["RpcWasmClient"] --> D["RpcDispatcher [muxio_core::rpc::RpcDispatcher]"]
C --> E["RpcServiceEndpoint [muxio_rpc_service_endpoint::RpcServiceEndpoint]"]
C --> CB["emit_callback [Arc<dyn Fn(Vec<u8>)>]"]
C --> S["state_change_handler [RpcTransportStateChangeHandler]"]
end
D -.->|encodes frames| CB
E -.->|uses for response| D
“WASM Client Entity Map”
Sources: extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:14-32
Lifecycle and Data Flow
The client’s lifecycle is driven by external events, typically mapped from a JavaScript WebSocket object’s events (onopen, onmessage, onclose).
Connection Lifecycle
handle_connect: Called when the transport is established. It updatesis_connectedtotrueand triggers theRpcTransportState::Connectedevent via the registered handler extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:35-41handle_disconnect: Called when the transport fails or closes. It marks the client as disconnected and invokesfail_all_pending_requestson the dispatcher withFrameDecodeError::ReadAfterCancelto clean up any awaiting RPC futures extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:58-68
The read_bytes Pipeline
The read_bytes method processes incoming binary data from the network. It delegates to the internal RpcServiceEndpoint, which handles the decoding and routing of both prebuffered and streaming RPC messages extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:46-55
“WASM Read Bytes Data Flow”
Sources: extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:46-55 extensions/muxio-rpc-service-endpoint/tests/prebuffered_endpoint_tests.rs:71-75
Static Client Pattern
To simplify integration with JavaScript and avoid complex state management across the WASM boundary, the crate provides a “Static Client” pattern. This allows the WASM module to maintain a single, global RpcWasmClient instance extensions/muxio-wasm-rpc-client/src/static_lib/static_client.rs:9-11
Global Reference
The MUXIO_STATIC_RPC_CLIENT_REF is a thread-local RefCell that holds an Option<Arc<RpcWasmClient>>. It is typically initialized once during the WASM startup phase extensions/muxio-wasm-rpc-client/src/static_lib/static_client.rs10
Key Static Functions
init_static_client(): Idempotent initialization of the global client. It sets up theemit_callbackto point to thestatic_muxio_write_bytesbridge, which communicates back to JS extensions/muxio-wasm-rpc-client/src/static_lib/static_client.rs:25-36with_static_client_async(f): The primary interface for making RPC calls from WASM. It retrieves the static client and executes an async closure, returning a JavaScriptPromiseviawasm_bindgen_futures::future_to_promiseextensions/muxio-wasm-rpc-client/src/static_lib/static_client.rs:54-72
Sources: extensions/muxio-wasm-rpc-client/src/static_lib/static_client.rs:9-82
JavaScript Bridge
The bridge uses wasm-bindgen to export functions to JavaScript and import networking functions from the host environment.
Exported to JS
These functions are decorated with #[wasm_bindgen] and are intended to be called by the JavaScript WebSocket wrapper:
static_muxio_read_bytes_uint8(inbound_data): Entry point for binary data arriving from the network. It converts theUint8Arrayto a RustVec<u8>and passes it to the static client extensions/muxio-wasm-rpc-client/src/static_lib/static_transport_bridge.rs:19-31static_muxio_handle_connect(): Bridges the JSonopenevent to the Rust client’s connection logic extensions/muxio-wasm-rpc-client/src/static_lib/static_transport_bridge.rs:34-43static_muxio_handle_disconnect(): Bridges JSoncloseoronerrorevents to the Rust client’s disconnection logic extensions/muxio-wasm-rpc-client/src/static_lib/static_transport_bridge.rs:46-55
Imported from JS
The WASM module expects the host environment to provide:
static_muxio_write_bytes_uint8(data): An external JS function that takes aUint8Arrayand transmits it via the network (e.g.,socket.send(data)) extensions/muxio-wasm-rpc-client/src/static_lib/static_transport_bridge.rs:8-11
“JS-WASM Bridge Interaction”
Sources: extensions/muxio-wasm-rpc-client/src/static_lib/static_transport_bridge.rs:7-55 extensions/muxio-wasm-rpc-client/src/static_lib/static_client.rs29
RpcServiceCallerInterface Implementation
RpcWasmClient implements the RpcServiceCallerInterface, allowing it to participate in the high-level RPC service ecosystem (e.g., using call_rpc_buffered) extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:89-115
| Method | Implementation |
|---|---|
get_dispatcher() | Returns an Arc<Mutex<RpcDispatcher>> extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:90-92 |
get_emit_fn() | Returns the internal emit_callback extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:94-96 |
is_connected() | Returns the current value of the is_connected atomic extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:98-100 |
set_state_change_handler() | Sets the handler and immediately triggers it if already connected extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:102-114 |
Sources: extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:89-115
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
IPC Transports & MPSC Adapter
Loading…
IPC Transports & MPSC Adapter
Relevant source files
- Cargo.lock
- extensions/muxio-tokio-mpsc-adapter/Cargo.toml
- extensions/muxio-tokio-mpsc-adapter/README.md
- extensions/muxio-tokio-mpsc-adapter/src/client.rs
- extensions/muxio-tokio-mpsc-adapter/src/lib.rs
- extensions/muxio-tokio-mpsc-adapter/src/server.rs
- extensions/muxio-tokio-rpc-ipc-client/Cargo.toml
- extensions/muxio-tokio-rpc-ipc-client/README.md
- extensions/muxio-tokio-rpc-ipc-client/src/lib.rs
This page covers the Muxio extension crates designed for local Inter-Process Communication (IPC) and the adapter layer that bridges Muxio’s streaming RPC events to standard Tokio asynchronous channels.
IPC Transports
Muxio provides native IPC support through muxio-tokio-rpc-ipc-client and muxio-tokio-rpc-ipc-server. These crates utilize the interprocess library to provide a cross-platform abstraction for local communication: Unix Domain Sockets on Linux/macOS and Named Pipes on Windows extensions/muxio-tokio-rpc-ipc-client/Cargo.toml15
RpcIpcClient
The RpcIpcClient implementation mirrors the architecture of the WebSocket client but targets local socket addresses. It implements RpcServiceCallerInterface, allowing it to be used interchangeably with other transports for making RPC calls extensions/muxio-tokio-rpc-ipc-client/src/lib.rs:5-7
MPSC Adapter
The muxio-tokio-mpsc-adapter crate provides a high-level convenience layer for streaming RPC. While the core RpcDispatcher uses callback-based event handling, this adapter allows developers to interact with streams using standard tokio::sync::mpsc channels extensions/muxio-tokio-mpsc-adapter/README.md3
ChannelCallerExt (Client-Side)
The ChannelCallerExt trait extends any RpcServiceCallerInterface (such as RpcClient or RpcIpcClient) to support channel-based streaming extensions/muxio-tokio-mpsc-adapter/src/client.rs15
Data Flow: open_channel
When open_channel is called, the following sequence occurs:
- Validation : The client checks if the transport is active extensions/muxio-tokio-mpsc-adapter/src/client.rs:46-51
- Channel Creation : Two
mpsc::unbounded_channelpairs are created: one for the request stream and one for the response stream extensions/muxio-tokio-mpsc-adapter/src/client.rs:53-54 - Dispatcher Call : The underlying
RpcDispatcher::callis invoked. Arecv_fnclosure is registered to forwardRpcStreamEvent::PayloadChunkevents into the response channel extensions/muxio-tokio-mpsc-adapter/src/client.rs:73-92 - Background Task : A Tokio task is spawned to monitor the request receiver. As the user sends
Vec<u8>into the request channel, the task writes them to theRpcStreamEncoderand flushes extensions/muxio-tokio-mpsc-adapter/src/client.rs:116-126
ChannelEndpointExt (Server-Side)
The ChannelEndpointExt trait allows an RpcServiceEndpoint to register handlers that automatically pipe incoming stream data into an MPSC sender extensions/muxio-tokio-mpsc-adapter/src/server.rs:30-33
MpscSender Abstraction
To support both bounded and unbounded channels, the adapter defines the MpscSender trait extensions/muxio-tokio-mpsc-adapter/src/server.rs:13-15
mpsc::Sender<Vec<u8>>: Usestry_send(may fail if buffer is full) extensions/muxio-tokio-mpsc-adapter/src/server.rs:17-21mpsc::UnboundedSender<Vec<u8>>: Usessend(always succeeds unless the receiver is dropped) extensions/muxio-tokio-mpsc-adapter/src/server.rs:23-27
Logic Association: Channel Mapping
The following diagram illustrates how Muxio RPC events are mapped to Tokio MPSC entities.
| Entity | Code Symbol | Role |
|---|---|---|
| Request Writer | req_tx | UnboundedSender for client to push data to server extensions/muxio-tokio-mpsc-adapter/src/client.rs41 |
| Response Reader | resp_rx | UnboundedReceiver for client to consume server output extensions/muxio-tokio-mpsc-adapter/src/client.rs42 |
| Event Bridge | recv_fn | Closure converting RpcStreamEvent to channel messages extensions/muxio-tokio-mpsc-adapter/src/client.rs:73-74 |
| Lifecycle Guard | resp_tx_holder | Arc<Mutex<Option<...>>> used to drop the sender and close the channel on End/Error extensions/muxio-tokio-mpsc-adapter/src/client.rs71 |
Code Entity Space: Client Channel Flow
This diagram shows the relationship between the ChannelCallerExt and the core RpcDispatcher.
Sources: extensions/muxio-tokio-mpsc-adapter/src/client.rs:35-130 extensions/muxio-tokio-mpsc-adapter/src/server.rs:50-80
graph TD
subgraph "User Code Space"
[UserApp] -- "open_channel(method_id)" --> [ChannelCallerExt]
[UserApp] -- "send(Vec<u8>)" --> [req_tx]
[resp_rx] -- "recv()" --> [UserApp]
end
subgraph "MPSC Adapter Space"
[ChannelCallerExt] -- "spawns" --> [RequestTask]
[RequestTask] -- "poll" --> [req_rx]
[recv_fn] -- "send(Ok(bytes))" --> [resp_tx]
end
subgraph "Muxio Core Space"
[RequestTask] -- "write_bytes()" --> [RpcStreamEncoder]
[RpcDispatcher] -- "trigger(RpcStreamEvent)" --> [recv_fn]
end
[RpcStreamEncoder] -- "network I/O" --> [RemoteEndpoint]
[RemoteEndpoint] -- "network I/O" --> [RpcDispatcher]
Code Entity Space: Server Handler Registration
This diagram describes how the server-side MPSC adapter bridges the RpcServiceEndpoint to a work queue.
Sources: extensions/muxio-tokio-mpsc-adapter/src/server.rs:50-80 extensions/muxio-tokio-mpsc-adapter/src/server.rs:13-27
graph LR
subgraph "Endpoint Setup"
[Endpoint] -- "register_channel_handler(tx)" --> [StreamHandlerClosure]
end
subgraph "Runtime Execution"
[RpcDispatcher] -- "RpcStreamEvent::PayloadChunk" --> [StreamHandlerClosure]
[StreamHandlerClosure] -- "try_send_bytes()" --> [MpscSender]
[RpcStreamEvent::End] -- "None-ify" --> [Guard]
[Guard] -- "drops" --> [MpscSender]
end
[MpscSender] -- "wakes" --> [WorkerTask]
Implementation Details
Lifecycle and Cleanup
The adapter ensures that resources are cleaned up when a stream ends:
- Client Shutdown : When the user drops the
req_tx(request sender), the backgroundRequestTaskreceivesNonefromreq_rx, callsencoder.end_stream(), and terminates extensions/muxio-tokio-mpsc-adapter/src/client.rs:117-126 - Server/Remote Shutdown : If the remote side sends an
RpcStreamEvent::EndorRpcStreamEvent::Error, the adapter clears the internalOption<Sender>. Dropping the sender causes the user’s receiver (resp_rx) to returnNone, signaling the end of the stream extensions/muxio-tokio-mpsc-adapter/src/client.rs:87-89 extensions/muxio-tokio-mpsc-adapter/src/server.rs:72-74
Use Case Matrix
| Feature | register_channel_handler | register_stream_handler (Raw) |
|---|---|---|
| Complexity | Low (Standard Channels) | Medium (Callback Logic) |
| Lifecycle | Tied to a single RPC stream | Manually managed |
| Best For | Per-stream work queues | Shared sinks (e.g., PTY, Broadcast) |
| Backpressure | Managed by mpsc buffer | Manual via StreamResponder |
Sources: extensions/muxio-tokio-mpsc-adapter/src/server.rs:42-49
Sources:
extensions/muxio-tokio-rpc-ipc-client/Cargo.tomlextensions/muxio-tokio-rpc-ipc-client/src/lib.rsextensions/muxio-tokio-mpsc-adapter/src/lib.rsextensions/muxio-tokio-mpsc-adapter/src/client.rsextensions/muxio-tokio-mpsc-adapter/src/server.rs
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Examples & Demo Applications
Loading…
Examples & Demo Applications
Relevant source files
- LICENSE
- benches/README.md
- examples/example-muxio-rpc-service-definition/Cargo.toml
- examples/example-muxio-rpc-service-definition/src/lib.rs
- examples/example-muxio-rpc-service-definition/src/prebuffered.rs
- examples/example-muxio-ws-rpc-app/Cargo.toml
This section provides an overview of how the Muxio framework is utilized in practice through the provided example crates. The repository includes a structured approach to building RPC applications by separating the Service Definition (the “contract”) from the Application Implementation (the “logic”).
The examples demonstrate a complete end-to-end lifecycle: defining methods with bitcode serialization, registering handlers on a WebSocket server, and performing concurrent calls from a client.
High-Level Workflow
The Muxio example ecosystem is split into two primary crates to demonstrate best practices for code sharing in distributed systems. These extensions serve as both functional utilities and architectural templates for building on Muxio’s core.
| Component | Role | Key Entities |
|---|---|---|
| Service Definition | Shared contract used by both Client and Server. | RpcMethodPrebuffered, rpc_method_id! |
| WS RPC Application | Implementation of logic and network transport. | RpcServer, RpcClient, register_prebuffered |
System Entity Mapping
The following diagram bridges the gap between the conceptual “Service” and the specific code entities used to implement it within the Muxio framework.
Service Definition to Code Mapping
graph TD
subgraph "Natural Language Space"
Contract["Service Contract"]
Method["RPC Method"]
ID["Method Identifier"]
end
subgraph "Code Entity Space"
Trait["RpcMethodPrebuffered"]
Struct_Add["prebuffered::Add"]
Struct_Mult["prebuffered::Mult"]
Struct_Echo["prebuffered::Echo"]
Macro["rpc_method_id!"]
end
Contract --> Trait
Method --> Struct_Add
Method --> Struct_Mult
Method --> Struct_Echo
ID --> Macro
subgraph "Implementation Entities"
Struct_Add -- "implements" --> Trait
Struct_Mult -- "implements" --> Trait
Struct_Echo -- "implements" --> Trait
Macro -- "defines" --> ID_VAL["METHOD_ID"]
end
Sources: examples/example-muxio-rpc-service-definition/Cargo.toml:1-13 examples/example-muxio-rpc-service-definition/src/lib.rs:1-5 examples/example-muxio-rpc-service-definition/src/prebuffered.rs:1-9
Shared Service Definition Pattern
The example-muxio-rpc-service-definition crate serves as the single source of truth for the RPC interface. By defining methods in a shared crate, both the client and server are guaranteed to use the same serialization logic and method identifiers.
This pattern utilizes the RpcMethodPrebuffered trait examples/example-muxio-rpc-service-definition/src/lib.rs4 to define how data is moved across the wire. The example implementation includes:
- Add : Performs summation of
Vec<f64>examples/example-muxio-rpc-service-definition/src/prebuffered.rs:1-2 - Mult : Performs multiplication of
Vec<f64>examples/example-muxio-rpc-service-definition/src/prebuffered.rs:7-8 - Echo : A round-trip test returning the input
Vec<u8>examples/example-muxio-rpc-service-definition/src/prebuffered.rs:4-5
For details on how to structure your own shared contracts and use the compile-time hashing macro, see Shared Service Definition Pattern.
Sources: examples/example-muxio-rpc-service-definition/Cargo.toml:2-12 examples/example-muxio-rpc-service-definition/src/lib.rs:1-5 examples/example-muxio-rpc-service-definition/src/prebuffered.rs:1-9
Full WebSocket RPC Application
The example-muxio-ws-rpc-app is a complete, runnable demonstration of the Muxio stack using the tokio runtime examples/example-muxio-ws-rpc-app/Cargo.toml17 It connects the service definitions to a live network transport.
Application Architecture & Code Entities
sequenceDiagram
participant C as "RpcClient (muxio-tokio-rpc-client)"
participant S as "RpcServer (muxio-tokio-rpc-server)"
participant E as "RpcServiceEndpoint (muxio-rpc-service-endpoint)"
Note over S, E: endpoint.register_prebuffered()
C->>S: RpcCallPrebuffered::call(Add)
S->>E: Dispatch by Add::METHOD_ID
E-->>S: Add::encode_response()
S-->>C: Response (Stream ID correlation)
This demo application showcases:
- Server Setup : Initializing
RpcServerand registering method handlers usingendpoint.register_prebuffered. - Concurrency : Using
tokio::join!to execute multiple RPC calls simultaneously over a single multiplexed connection. - State Management : Monitoring connection lifecycle events via
set_state_change_handler. - Benchmarking : High-performance roundtrip tests defined in
benches/roundtrip.rsexamples/example-muxio-ws-rpc-app/Cargo.toml:25-28
For a step-by-step walkthrough of the server and client implementation, see example-muxio-ws-rpc-app: Full WebSocket RPC Application.
Sources: examples/example-muxio-ws-rpc-app/Cargo.toml:10-28 benches/README.md:1-2
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Shared Service Definition Pattern
Loading…
Shared Service Definition Pattern
Relevant source files
- LICENSE
- benches/README.md
- examples/example-muxio-rpc-service-definition/Cargo.toml
- examples/example-muxio-rpc-service-definition/README.md
- examples/example-muxio-rpc-service-definition/src/lib.rs
- examples/example-muxio-rpc-service-definition/src/prebuffered.rs
The Shared Service Definition Pattern is a core architectural idiom in Muxio that allows both the client and the server to share a single source of truth for RPC method signatures and serialization logic. By defining services in a dedicated crate, developers ensure type safety and protocol consistency across different transport implementations (e.g., Tokio-based servers and WASM-based clients).
Purpose and Scope
The primary goal of this pattern is to decouple the what (the RPC contract) from the how (the network transport and runtime). This is achieved through the RpcMethodPrebuffered trait, which defines how high-level Rust types are transformed into binary payloads and identifies methods using unique 64-bit hashes.
In the provided examples, the example-muxio-rpc-service-definition crate serves as this shared contract, utilized by both the server and client.
Sources: examples/example-muxio-rpc-service-definition/src/lib.rs4 examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs17
Crate Structure
A typical service definition crate is lightweight and usually depends only on muxio-rpc-service and a serialization library like bitcode examples/example-muxio-rpc-service-definition/Cargo.toml:10-12 The example structure follows a modular approach:
add.rs: Implements a mathematical addition service examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs:1-44mult.rs: Implements a mathematical multiplication service examples/example-muxio-rpc-service-definition/src/prebuffered/mult.rs:1-44echo.rs: Implements a raw byte-array echo service examples/example-muxio-rpc-service-definition/src/prebuffered/echo.rs:1-27
The crate re-exposes the RpcMethodPrebuffered trait for simplicity examples/example-muxio-rpc-service-definition/src/lib.rs4
Sources: examples/example-muxio-rpc-service-definition/src/lib.rs:1-5 examples/example-muxio-rpc-service-definition/src/prebuffered.rs:1-9 examples/example-muxio-rpc-service-definition/Cargo.toml:1-13
Implementation: RpcMethodPrebuffered
The RpcMethodPrebuffered trait is the cornerstone of the shared definition. It requires the implementation of four serialization methods and a unique METHOD_ID.
Method Identification via rpc_method_id!
To avoid manual management of integer IDs, Muxio uses the rpc_method_id! macro. This macro generates a u64 at compile-time by hashing a string literal (e.g., "math.add") using the XXH3 algorithm examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs18 This ensures that as long as the string name is consistent, the client and server will agree on the dispatch ID.
Data Flow and Serialization
The pattern typically uses a serialization library (like bitcode) to handle the conversion of parameters into bytes examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs1
| Stage | Function | Direction |
|---|---|---|
| Request Encoding | encode_request | Caller: Input -> Vec<u8> |
| Request Decoding | decode_request | Endpoint: &[u8] -> Input |
| Response Encoding | encode_response | Endpoint: Output -> Vec<u8> |
| Response Decoding | decode_response | Caller: &[u8] -> Output |
Example: The Add Service
In add.rs, the service defines internal structs for request and response parameters that are hidden from the public API of the Add unit struct.
Entity Mapping: Add Service
graph TD
subgraph "Natural Language Space"
"Math Addition Service"
end
subgraph "Code Entity Space"
Add["struct Add"]
AddReq["struct AddRequestParams"]
AddRes["struct AddResponseParams"]
Trait["RpcMethodPrebuffered"]
Add -- "implements" --> Trait
AddReq -- "serialized by" --> Add
AddRes -- "serialized by" --> Add
Add -- "uses" --> rpc_method_id["rpc_method_id!('math.add')"]
end
Sources: examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs:5-15 examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs:17-18
Detailed Method Implementations
Structured Data: Add and Mult
The Add and Mult implementations use bitcode to handle Vec<f64> inputs.
AddImplementation: DefinesMETHOD_IDasrpc_method_id!("math.add")examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs18 It maps aVec<f64>input to a singlef64output examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs:20-21MultImplementation: Mirrors theAddstructure but usesrpc_method_id!("math.mult")examples/example-muxio-rpc-service-definition/src/prebuffered/mult.rs18
Passthrough: Echo
The Echo service demonstrates a “raw” implementation where no external serialization is needed because the Input and Output types are already Vec<u8> examples/example-muxio-rpc-service-definition/src/prebuffered/echo.rs:9-10 The implementation simply returns the input bytes or clones them into a vector examples/example-muxio-rpc-service-definition/src/prebuffered/echo.rs:12-26
sequenceDiagram
participant Client as "RpcClient (Caller)"
participant Shared as "example-muxio-rpc-service-definition"
participant Server as "RpcServer (Endpoint)"
Note over Client, Server: Both crates depend on Shared Definition
rect rgb(240, 240, 240)
Note right of Client: call_rpc_buffered::<Add>(...)
Client->>Shared: encode_request(Vec<f64>)
Shared-->>Client: Vec<u8> (Payload)
end
Client->>Server: Frame (METHOD_ID: math.add)
rect rgb(240, 240, 240)
Note left of Server: handle_request (Add)
Server->>Shared: decode_request(Vec<u8>)
Shared-->>Server: Vec<f64> (Input)
Note left of Server: Execute Logic
Server->>Shared: encode_response(f64)
Shared-->>Server: Vec<u8> (Payload)
end
Server->>Client: Frame (Response)
rect rgb(240, 240, 240)
Client->>Shared: decode_response(Vec<u8>)
Shared-->>Client: f64 (Output)
end
Shared Usage Diagram
The following diagram illustrates how the shared crate bridges the Client and Server components by providing common serialization logic.
Protocol Interaction Flow
Sources: examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs:23-43 examples/example-muxio-rpc-service-definition/src/prebuffered/echo.rs:6-27
Key Functions and Traits
RpcMethodPrebuffered: The trait that defines the interface for a specific RPC method examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs17rpc_method_id!: A macro that generates a uniqueu64identifier based on a string name examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs18bitcode::encode/bitcode::decode: Used within the trait methods to transform parameters into the binary format required for transport examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs:24-29
Sources:
- examples/example-muxio-rpc-service-definition/src/lib.rs
- examples/example-muxio-rpc-service-definition/src/prebuffered/add.rs
- examples/example-muxio-rpc-service-definition/src/prebuffered/mult.rs
- examples/example-muxio-rpc-service-definition/src/prebuffered/echo.rs
- examples/example-muxio-rpc-service-definition/Cargo.toml
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
example-muxio-ws-rpc-app: Full WebSocket RPC Application
Loading…
example-muxio-ws-rpc-app: Full WebSocket RPC Application
Relevant source files
This page walks through the example-muxio-ws-rpc-app, a complete reference implementation of a WebSocket-based RPC system. It demonstrates how to integrate the server and client crates to perform concurrent, type-safe RPC calls using shared service definitions.
Application Architecture
The application follows a standard client-server model where both parties agree on a shared service contract defined in a separate crate. The server uses RpcServer (from muxio-tokio-rpc-server) to listen for WebSocket connections, while the client uses RpcClient (from muxio-tokio-rpc-client) to initiate requests.
Data Flow Overview
The diagram below illustrates the lifecycle of an RPC call from the client to the server and back.
RPC Roundtrip Lifecycle
sequenceDiagram
participant C as "RpcClient"
participant S as "RpcServer"
participant E as "RpcServiceEndpoint"
participant H as "RegisteredHandler"
Note over C, H: Connection Established
C->>S: WebSocket Binary Message (Encoded RpcRequest)
S->>E: read_bytes(payload, context)
E->>E: Identify Method (METHOD_ID)
E->>H: Execute async closure
H-->>E: Return response_bytes
E-->>S: Return Result<Bytes>
S->>C: WebSocket Binary Message (Encoded RpcResponse)
Note over C: Future resolves with result
Sources: examples/example-muxio-ws-rpc-app/Cargo.toml:12-16
Server Setup and Handler Registration
The server is initialized by binding to a TcpListener and registering handlers for specific METHOD_IDs defined in the shared service definition.
Implementation Details
- Initialization : The server is typically created using
RpcServer::new(None)and wrapped in anArcfor sharing. - Endpoint Acquisition : The
RpcServiceEndpointis retrieved viaserver.endpoint(). - Registration : Handlers for methods like
Add,Mult, andEchoare registered usingendpoint.register_prebuffered. Each handler is anasync moveclosure that decodes the request using the shared definition’sdecode_request, performs logic, and encodes the response viaencode_response. - Execution : The server is spawned into a Tokio task using
server.serve_with_listener(listener).
| Component | Role | Source |
|---|---|---|
RpcServer | Tokio-based WebSocket server implementation | examples/example-muxio-ws-rpc-app/Cargo.toml16 |
RpcServiceEndpoint | Registry for RPC method handlers | examples/example-muxio-ws-rpc-app/Cargo.toml13 |
example-muxio-rpc-service-definition | Shared contract (Add, Mult, Echo) | examples/example-muxio-ws-rpc-app/Cargo.toml12 |
Sources: examples/example-muxio-ws-rpc-app/Cargo.toml:10-19
Client Connection and Concurrent Calls
The client connects to the server’s WebSocket endpoint and performs multiple RPC calls concurrently.
State Change Handlers
The client can monitor the health of the connection by setting a state change handler. This is useful for logging or triggering reconnection logic.
- Function :
rpc_client.set_state_change_handler(...). - States :
RpcTransportState(e.g.,Connected,Disconnected).
Concurrent RPCs with tokio::join!
Because muxio is multiplexed, the client can send multiple requests over a single connection without waiting for previous ones to finish. In a typical implementation, different calls are awaited simultaneously using tokio::join!.
Code Entity Mapping
graph TD
subgraph ClientSpace ["Client Application (example-muxio-ws-rpc-app)"]
A["tokio::join!"] --> B["Add::call"]
A --> C["Mult::call"]
A --> D["Echo::call"]
end
subgraph CoreSpace ["Muxio Core (RpcDispatcher)"]
B --> E["call_rpc_buffered"]
E --> F["RpcSession::allocate_stream_id"]
end
subgraph TransportSpace ["Tokio Transport (RpcClient)"]
F --> H["RpcClient::new"]
end
Sources: examples/example-muxio-ws-rpc-app/Cargo.toml:10-17
Roundtrip Benchmarks
The example includes a criterion benchmark to measure the performance of the full stack.
Benchmark Scenarios
- Batch Throughput : Measures the time to complete multiple concurrent RPC requests. This tests the system’s ability to handle overlapped I/O and task scheduling.
- Single Latency : Measures the baseline roundtrip latency for a single RPC call. This captures the overhead of encoding, TCP transmission, server execution, and decoding.
graph LR
subgraph BenchInit ["Benchmark Initialization (roundtrip)"]
I["tokio::runtime"] --> J["TcpListener::bind"]
J --> K["RpcServer::new"]
K --> L["endpoint.register_prebuffered"]
L --> M["tokio::spawn(server.serve)"]
M --> N["RpcClient::new"]
end
N --> O["Criterion Iteration"]
O --> P["RpcCallPrebuffered::call"]
Performance Path
The benchmark utilizes the same register_prebuffered and method calling patterns used in the main application, ensuring that the performance metrics reflect real-world usage of the library.
Benchmark Setup Diagram
Sources: examples/example-muxio-ws-rpc-app/Cargo.toml:21-27
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Testing Infrastructure
Loading…
Testing Infrastructure
Relevant source files
The Muxio project employs a multi-layered testing strategy designed to validate the reliability of the binary framing protocol, the RPC multiplexing engine, and the various transport implementations (Tokio, IPC, and WASM). The infrastructure is split between unit tests within the core crate and a specialized integration testing harness used to bypass circular dependency issues during the publishing process.
Testing Strategy Overview
The testing architecture is divided into three primary tiers:
- Core Unit & Integration Tests: Located in the
muxio-corecrate, these validate the fundamental logic of theFrameandRPClayers using in-memory buffers. - Extension Integration Tests : Located in the
muxio-ext-testcrate, these perform end-to-end validation of network transports (WebSocket, IPC, MPSC) and complex scenarios like concurrent calls and WASM bridging. - Continuous Integration : A GitHub Actions pipeline that ensures cross-platform compatibility, feature-flag consistency, and code coverage.
Workspace Test Distribution
| Test Category | Location | Primary Focus |
|---|---|---|
| Core Unit Tests | muxio-core/src/ | Internal logic of FrameCodec, RpcDispatcher, and RpcSession. |
| Core Integration Tests | muxio-core/tests/ | Interaction between Frame and RPC layers without external networking. |
| Transport Integration | extensions/muxio-ext-test/tests/ | RpcServer and RpcClient interaction over real sockets and IPC. |
| CI Configuration | .github/workflows/rust-tests.yml | Multi-OS testing, cargo-llvm-cov, and workspace-wide validation. |
Sources: .github/workflows/rust-tests.yml:1-30 extensions/muxio-ext-test/Cargo.toml:1-32
Core Library Tests
The core library tests focus on the state machines governing stream lifecycles and multiplexing. These tests ensure that the FrameMuxStreamDecoder correctly reassembles interleaved frames and that the RpcDispatcher maintains request-response correlation under high concurrency.
For details on specific test suites like rpc_dispatcher_tests and frame_stream_tests, see Core Library Tests.
Integration Tests & muxio-ext-test Harness
A unique challenge in the Muxio workspace is the circular dependency between transport crates and the test utilities that require them. To resolve this for crate publishing, all integration tests for extension crates reside in the muxio-ext-test crate. This crate is a utility package that exists solely to house dependencies on all other workspace members, including muxio-tokio-rpc-server, muxio-tokio-rpc-client, muxio-wasm-rpc-client, and the IPC transports extensions/muxio-ext-test/Cargo.toml:14-32
Automated Test Discovery
The muxio-ext-test crate allows developers to validate complex interactions across crates—such as the muxio-tokio-mpsc-adapter or muxio-tokio-rpc-ipc-server—without cluttering the individual crates’ dev-dependencies.
Code Entity Mapping: Test Environment
The following diagram illustrates how the muxio-ext-test crate acts as a bridge to test the various transport implementations.
Integration Test Architecture
graph TD
subgraph "muxio-ext-test [Harness]"
TT["TestTransport Trait"]
TM["Test Macros"]
end
subgraph "Transport Under Test"
WS["muxio-tokio-rpc-server / client"]
IPC["muxio-tokio-rpc-ipc-server / client"]
WASM["muxio-wasm-rpc-client"]
end
subgraph "Service Layer"
SD["example-muxio-rpc-service-definition"]
EP["muxio-rpc-service-endpoint"]
end
TT --> WS
TT --> IPC
TT --> WASM
WS & IPC &
WASM --> SD
WS &
IPC --> EP
Sources: extensions/muxio-ext-test/Cargo.toml:14-32 extensions/muxio-ext-test/README.md:1-14
For details on transport-specific tests and the proxy error propagation scenario, see Integration Tests & muxio-ext-test Harness.
Continuous Integration (CI)
The project utilizes GitHub Actions to maintain code quality across different environments. The rust-tests.yml workflow is configured to run on every push to main and for all pull requests .github/workflows/rust-tests.yml:6-10
CI Execution Flow
Sources: .github/workflows/rust-tests.yml:19-29 .github/workflows/rust-tests.yml:77-78 .github/workflows/rust-tests.yml:104-123
The CI pipeline ensures that the workspace is tested with --all-features to validate the various feature flag combinations, such as the tokio_support feature in the endpoint crate .github/workflows/rust-tests.yml78 It also generates coverage reports using cargo-llvm-cov to track testing depth across the core and extension modules .github/workflows/rust-tests.yml:167-169
Error Validation
Testing infrastructure also includes explicit validation of error types defined in the core. This includes FrameEncodeError and FrameDecodeError to ensure that the system handles corrupt data or protocol violations gracefully. These tests are critical for the FrameStreamEncoder and FrameMuxStreamDecoder components that form the backbone of the transport layer.
Sources: .github/workflows/rust-tests.yml:77-87 extensions/muxio-ext-test/Cargo.toml:20-23
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Core Library Tests
Loading…
Core Library Tests
Relevant source files
- core/Cargo.toml
- core/src/rpc/rpc_dispatcher.rs
- core/src/rpc/rpc_internals/rpc_respondable_session.rs
- core/src/rpc/rpc_internals/rpc_trait.rs
- extensions/muxio-ext-test/src/endpoint_helpers.rs
- tests/rpc_dispatcher_tests.rs
- tests/rpc_respondable_session_tests.rs
- tests/rpc_stream_tests.rs
- tests/stream_termination_tests.rs
The tests/ directory contains the primary validation suite for the muxio core library. These tests cover the entire stack from low-level binary framing to high-level RPC dispatching and stream lifecycle management.
1. Frame Layer Tests
The frame layer tests validate the binary protocol’s ability to handle chunking, reassembly, and multiplexing across independent streams.
frame_stream_tests
This suite validates the FrameStreamEncoder and FrameMuxStreamDecoder implementations.
- Chunking & Reassembly: Ensures that a single
write_bytescall exceedingmax_chunk_sizeis split into multiple frames and correctly reassembled by the decoder tests/frame_stream_tests.rs:7-44 - Multiplexing : Simulates two independent streams (
stream_id100 and 200) with interleaved bytes. It validates that theFrameMuxStreamDecodercorrectly routes payloads to their respective streams tests/frame_stream_tests.rs:75-146 - Out-of-Order Handling : Shuffles emitted frames to simulate network jitter. It validates that the decoder uses
seq_idto reorder frames before yielding them tests/frame_stream_tests.rs:149-186 - Incomplete Input : Validates that the decoder can handle partial frames (split across multiple
read_bytescalls) without losing data tests/frame_stream_tests.rs:47-72 - Marker Frames : Verifies that
end_streamemits aFrameKind::Endframe with an empty payload tests/frame_stream_tests.rs:189-220
stream_termination_tests
Focuses on the lifecycle of a stream, specifically how it handles closure and cancellation.
- Cancellation : Validates that calling
cancel_stream()on aFrameStreamEncodertests/stream_termination_tests.rs:23-27 prevents further writes and emits aFrameDecodeError::ReadAfterCancelon the decoder side tests/stream_termination_tests.rs:46-56 - Post-Termination Safety : Ensures that attempts to write or cancel after a stream has already ended or been canceled result in a
WriteAfterCancelorWriteAfterEnderror tests/stream_termination_tests.rs:29-41 - Auto-Flush : Confirms that
end_stream()automatically flushes any buffered data before sending theFrameKind::Endmarker tests/stream_termination_tests.rs:158-200 - RPC Abort : Validates that
RpcSessioncorrectly propagates termination errors when an underlying stream is canceled or ended tests/stream_termination_tests.rs:60-155
Sources: tests/frame_stream_tests.rs:1-223 tests/stream_termination_tests.rs:1-201
2. RPC Layer Tests
These tests validate the RpcSession, RpcDispatcher, and RpcRespondableSession components which manage request/response correlation and streaming.
rpc_stream_tests
Validates the low-level RpcSession and RpcStreamEncoder.
- Parallel Streams : Simulates two concurrent RPC calls. It validates that headers (containing
rpc_method_idandrpc_metadata_bytes) are correctly associated with their subsequent payload chunks even when interleaved tests/rpc_stream_tests.rs:9-165 - Metadata Integrity : Specifically tests large or complex metadata structures (serialized via
bitcode) to ensure they are correctly transmitted in theRpcHeadertests/rpc_stream_tests.rs:168-220
rpc_dispatcher_tests
Validates the RpcDispatcher core/src/rpc/rpc_dispatcher.rs:36-51 which provides a higher-level API for calling and responding.
- Call/Respond Loop : Demonstrates a full loop where a client calls a method tests/rpc_dispatcher_tests.rs:74-123 a server reads the bytes, executes logic (like an
ADDorMULTfunction), and responds. It validates the use ofRpcStreamEventfor handling incoming data tests/rpc_dispatcher_tests.rs:85-119 - Request Deletion : Confirms that
delete_rpc_requestcore/src/rpc/rpc_dispatcher.rs:144-146 correctly cleans up internal state once a request is processed.
rpc_respondable_session_tests
Tests the RpcRespondableSession, which adds support for “catch-all” handlers and pre-buffering.
- Catch-All Handlers : Validates
set_catch_all_response_handlercore/src/rpc/rpc_internals/rpc_respondable_session.rs:106-111 which allows a session to process incoming requests that don’t have a specific pre-registered handler tests/rpc_respondable_session_tests.rs:32-63 - Bidirectional Flow : Simulates a client initiating a
Calland the server responding with aResponseusingstart_reply_streamtests/rpc_respondable_session_tests.rs:121-136 - Pre-buffering Toggle : Validates behavior when
is_prebuffering_responseis toggled, ensuring bytes are accumulated into a singlePayloadChunkwhen enabled tests/rpc_respondable_session_tests.rs:7-162
rpc_dispatcher_prebuffered_tests
A specialized suite for the common “Request-Response” pattern where the entire payload is known upfront.
- Synchronous-style Simulation : Uses local dispatchers to simulate a synchronous RPC call by pre-buffering the request parameters and waiting for a finalized response.
Sources: tests/rpc_stream_tests.rs:1-220 tests/rpc_dispatcher_tests.rs:1-170 tests/rpc_respondable_session_tests.rs:1-163 core/src/rpc/rpc_dispatcher.rs:1-170 core/src/rpc/rpc_internals/rpc_respondable_session.rs:1-180
3. Implementation & Data Flow Diagrams
RPC Call to Byte Emission
The following diagram traces the path from an RpcRequest in a test to the raw bytes emitted by the FrameStreamEncoder.
| Entity | Role |
|---|---|
RpcRequest | High-level request definition containing method ID and params tests/rpc_dispatcher_tests.rs:42-49 |
RpcDispatcher | Orchestrates the call, manages request IDs, and invokes the encoder core/src/rpc/rpc_dispatcher.rs:36-51 |
RpcStreamEncoder | Serializes the RpcHeader into frames and manages chunked writes core/src/rpc/rpc_internals/rpc_respondable_session.rs:48-74 |
FrameStreamEncoder | Encapsulates binary framing, handles chunking, and invokes the on_emit callback tests/stream_termination_tests.rs:11-13 |
Data Flow: RPC Dispatching
Sources: core/src/rpc/rpc_dispatcher.rs:74-123 tests/rpc_dispatcher_tests.rs:74-123 core/src/rpc/rpc_internals/rpc_respondable_session.rs:48-74
graph LR
subgraph "Input"
BYTES["&[u8] from Transport"]
end
subgraph "Processing (Code Entities)"
DECODER["FrameMuxStreamDecoder::read_bytes()"]
SESSION["RpcRespondableSession::read_bytes()"]
ROUTER["RpcStreamMethodRouter (Optional)"]
EVENT["RpcStreamEvent::Header / PayloadChunk"]
end
subgraph "Validation"
ASSERT["assert_eq!(received_payload, expected)"]
end
BYTES --> DECODER
DECODER --> SESSION
SESSION --> ROUTER
ROUTER --> EVENT
EVENT --> ASSERT
RPC Byte Reception to Stream Events
This diagram shows how raw bytes are processed back into high-level events within the test suites, bridging the gap between binary transport and application logic.
Data Flow: RPC Byte Reception
Sources: tests/rpc_stream_tests.rs:17-60 core/src/rpc/rpc_internals/rpc_respondable_session.rs:113-143 core/src/rpc/rpc_internals/rpc_trait.rs:22-23
4. Utility Tests
The utils_tests.rs file covers foundational logic used across the library for timekeeping and identity management.
| Function | Validation |
|---|---|
now() | Ensures monotonicity and alignment with system time (within 5ms) tests/utils_tests.rs:6-25 |
increment_u32_id() | Validates uniqueness across 10,000 consecutive calls using a HashSet tests/utils_tests.rs:28-35 |
Sources: tests/utils_tests.rs:1-36
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Integration Tests & muxio-ext-test Harness
Loading…
Integration Tests & muxio-ext-test Harness
Relevant source files
- .gitignore
- extensions/muxio-ext-test/README.md
- extensions/muxio-ext-test/build.rs
- extensions/muxio-ext-test/src/ipc_helpers.rs
- extensions/muxio-ext-test/src/lib.rs
- extensions/muxio-ext-test/src/test_assertions.rs
- extensions/muxio-ext-test/src/test_suites.rs
- extensions/muxio-ext-test/src/test_transport.rs
- extensions/muxio-ext-test/src/transports/ipc.rs
- extensions/muxio-ext-test/src/transports/mod.rs
- extensions/muxio-ext-test/src/transports/wasm.rs
- extensions/muxio-ext-test/src/transports/ws.rs
- extensions/muxio-ext-test/src/wasm_helpers.rs
- extensions/muxio-ext-test/src/ws_helpers.rs
- extensions/muxio-ext-test/tests/complex_concurrent_tests.rs
- extensions/muxio-ext-test/tests/mpsc_adapter_tests.rs
- extensions/muxio-ext-test/tests/muxio-tokio-rpc-server/proxy_error_propagation_tests.rs
- extensions/muxio-ext-test/tests/prebuffered_roundtrip_tests.rs
- extensions/muxio-ext-test/tests/prebuffered_server_to_client_tests.rs
- extensions/muxio-ext-test/tests/registration_conflict_tests.rs
- extensions/muxio-ext-test/tests/streaming_handler_tests.rs
- extensions/muxio-ext-test/tests/transport_state_tests.rs
The Muxio testing infrastructure is designed to validate the entire RPC stack, from binary framing up to high-level service definitions, across multiple runtimes (Tokio and WASM) and transport types (WS, IPC, and MPSC). While unit tests reside within individual crates, complex integration tests—especially those involving circular dependencies between the client and server—are housed in a specialized harness.
muxio-ext-test: The Integration Harness
The muxio-ext-test crate is a utility library whose primary purpose is to provide a unified environment for integration tests that require both muxio-tokio-rpc-client and muxio-tokio-rpc-server extensions/muxio-ext-test/src/lib.rs:1-8 By placing tests here, the project avoids circular dependency issues during the cargo publish process extensions/muxio-ext-test/README.md:1-3
The TestTransport Trait
To achieve transport-agnostic testing, the harness defines the TestTransport trait extensions/muxio-ext-test/src/test_transport.rs:9-37 Any transport (WS, IPC, WASM, MPSC) that implements this trait can run the entire suite of integration tests.
| Method | Purpose |
|---|---|
connect() | Starts a server and returns a connected client with standard handlers (Add, Mult, Echo) registered extensions/muxio-ext-test/src/test_transport.rs18 |
connect_fail() | Validates that connecting to a non-existent endpoint returns an io::Error extensions/muxio-ext-test/src/test_transport.rs20 |
connect_with_disconnect() | Sets up a connection that can be explicitly closed via a oneshot::Sender to test cleanup logic extensions/muxio-ext-test/src/test_transport.rs21 |
connect_s2c() | Establishes a connection where the server holds a handle to call the client extensions/muxio-ext-test/src/test_transport.rs:22-26 |
Automated Test Discovery
The harness uses a custom build.rs to automatically discover and include test files.
- Scanning : It recursively scans the
tests/directory for.rsfiles extensions/muxio-ext-test/build.rs:19-21 - Generation : It generates a file named
auto_tests.rsextensions/muxio-ext-test/build.rs:24-25 - Module Mapping : Each discovered file is wrapped in a unique module and included via the
include!macro extensions/muxio-ext-test/build.rs:40-51
Sources: extensions/muxio-ext-test/src/test_transport.rs:1-37 extensions/muxio-ext-test/build.rs:7-57 extensions/muxio-ext-test/README.md:5-13
Unified Test Suites
The harness provides macros to instantiate test suites for specific transports. These suites are defined in src/test_suites.rs extensions/muxio-ext-test/src/test_suites.rs:1-21
Prebuffered Roundtrip Tests
Generated via the prebuffered_roundtrip_tests! macro extensions/muxio-ext-test/src/lib.rs:12-44 these validate:
- Success : Concurrent execution of
Add,Mult, andEchocalls usingtokio::join!extensions/muxio-ext-test/src/test_suites.rs:21-36 - Error Propagation : Ensures that a handler returning an error results in an
RpcServiceError::Rpcwith the correct message extensions/muxio-ext-test/src/test_suites.rs:40-63 - Large Payloads : Validates that payloads (e.g., 100KB) exceeding chunk limits are handled correctly extensions/muxio-ext-test/src/test_suites.rs:66-70
- Method Not Found : Asserts that calling an unregistered ID returns
RpcServiceErrorCode::NotFoundextensions/muxio-ext-test/src/test_suites.rs:73-97
Server-to-Client (S2C) Tests
Generated via server_to_client_tests! extensions/muxio-ext-test/src/lib.rs:48-107
- Client Registration : The client registers a handler on its own
RpcServiceEndpointextensions/muxio-ext-test/src/test_suites.rs:178-184 - Server Initiation : The server uses a
ConnectionContextHandle(orRpcIpcConnectionContextHandle) to initiate a call to the client extensions/muxio-ext-test/src/test_suites.rs187 - Throughput & Concurrency: Tests like
concurrent_bidirectional_streamingpush data in both directions simultaneously to stress the frame multiplexer extensions/muxio-ext-test/src/test_suites.rs:79-90
Transport State Tests
Generated via transport_state_tests! extensions/muxio-ext-test/src/lib.rs:111-113
- State Change Handler : Verifies that
set_state_change_handlertriggersConnectedthenDisconnectedtransitions extensions/muxio-ext-test/src/lib.rs:126-163 - Request Cancellation : Ensures that pending requests fail immediately with a
ConnectionAbortederror if the transport drops extensions/muxio-ext-test/src/lib.rs:166-189
Sources: extensions/muxio-ext-test/src/test_suites.rs:21-198 extensions/muxio-ext-test/src/lib.rs:12-189 extensions/muxio-ext-test/README.md:17-25
Transport-Specific Implementations
Each transport implements the TestTransport trait to hook into the unified suites.
WebSocket (WS) & IPC
The WS implementation (src/transports/ws.rs) uses setup_ws_server and connect_ws_client helpers extensions/muxio-ext-test/src/transports/ws.rs:28-33 The IPC implementation (src/transports/ipc.rs) utilizes interprocess to create local sockets with unique names extensions/muxio-ext-test/src/transports/ipc.rs:19-45
WASM Bridge Implementation
Since RpcWasmClient is designed for browser environments, the integration test uses a setup_wasm_bridge helper extensions/muxio-ext-test/src/transports/wasm.rs:157-163
Title: WASM Integration Test Data Flow
Sources: extensions/muxio-ext-test/src/transports/ws.rs:19-141 extensions/muxio-ext-test/src/transports/ipc.rs:25-156 extensions/muxio-ext-test/src/transports/wasm.rs:18-190
Complex Integration Scenarios
Proxy Error Propagation
This test validates error handling in a multi-hop scenario: Client A - > Server (Proxy) -> Client B (Provider) extensions/muxio-ext-test/tests/muxio-tokio-rpc-server/proxy_error_propagation_tests.rs:1-6
- The Proxy : The server registers an
Echohandler that internally callsEcho::callon Client B’s handle extensions/muxio-ext-test/tests/muxio-tokio-rpc-server/proxy_error_propagation_tests.rs:78-99 - Failure Injection : Client B is disconnected while Client A’s call is pending.
- Verification : The server must catch the failure and return a
ConnectionAbortederror to Client A extensions/muxio-ext-test/tests/muxio-tokio-rpc-server/proxy_error_propagation_tests.rs:106-115
Streaming & Registration Conflicts
- Streaming Handler :
tests/streaming_handler_tests.rsvalidates theregister_stream_handlerpipeline, ensuringRpcStreamEvent(Payload/End) sequences are correctly delivered extensions/muxio-ext-test/src/transports/ipc.rs:125-144 - Registration Conflicts :
tests/registration_conflict_tests.rsensures that attempting to register the sameMETHOD_IDtwice on anRpcServiceEndpointreturns an error.
classDiagram
class TestTransport {<<trait>>\n+connect()\n+connect_s2c()}
class RpcIpcClient {
+get_endpoint()
}
class RpcWasmClient {+handle_connect()\n+read_bytes()}
class RpcClient {+new()}
TestTransport <|-- RpcIpcClient
TestTransport <|-- RpcWasmClient
TestTransport <|-- RpcClient
RpcIpcClient ..> RpcIpcServer : tests against
RpcClient ..> RpcServer : tests against
RpcWasmClient ..> RpcServer : tests via bridge
Title: Transport Component Relationships
Sources: extensions/muxio-ext-test/tests/muxio-tokio-rpc-server/proxy_error_propagation_tests.rs:25-126 extensions/muxio-ext-test/src/test_suites.rs:125-155 extensions/muxio-ext-test/src/transports/mod.rs:1-10
Dismiss
Refresh this wiki
Enter email to refresh
This documentation is part of the "Projects with Books" initiative at zenOSmosis.
The source code for this project is available on GitHub.
Glossary
Loading…
Glossary
Relevant source files
- Cargo.lock
- Cargo.toml
- DRAFT.md
- README.md
- extensions/muxio-rpc-service-caller/src/caller_interface.rs
- extensions/muxio-rpc-service-caller/src/lib.rs
- extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs
- extensions/muxio-rpc-service-caller/tests/dynamic_channel_tests.rs
- extensions/muxio-rpc-service-endpoint/src/error.rs
- extensions/muxio-rpc-service-endpoint/src/lib.rs
- extensions/muxio-rpc-service-endpoint/tests/prebuffered_endpoint_tests.rs
- extensions/muxio-tokio-rpc-client/src/rpc_client.rs
- extensions/muxio-tokio-rpc-server/src/rpc_server.rs
- extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs
This page provides definitions for the specific terminology, abbreviations, and domain concepts used within the Muxio framework. Muxio uses a layered architecture where concepts from the low-level framing layer are composed to build high-level RPC abstractions.
Core Concepts & Jargon
Binary-First / Framed Transport
Muxio operates on raw byte streams rather than text-based formats like JSON README.md:33-34 Data is transmitted in discrete, ordered chunks called Frames. This approach allows for zero-assumption serialization (e.g., bitcode, FlatBuffers, or raw f32 arrays) DRAFT.md:11-13
Bidirectional Symmetry
Unlike traditional HTTP where roles are strictly Requestor (Client) and Responder (Server), Muxio allows both ends of a connection to act as both a client and a server simultaneously DRAFT.md:15-16 A “Client” in Muxio can register handlers to receive calls from the “Server” via the RpcServiceEndpointInterface extensions/muxio-rpc-service-endpoint/src/endpoint_interface.rs:1-12
Layered Transport Kit
A design philosophy where the core logic is written in a non-async, callback-driven style DRAFT.md:43-48 This allows the same core multiplexing logic to be wrapped by different “Transport Kits” like Tokio for native apps or wasm-bindgen for web browsers README.md:35-41
Sources: README.md:17-41 DRAFT.md:11-16 DRAFT.md:43-48
Technical Terms
| Term | Definition | Key Code Entity |
|---|---|---|
| Dispatcher | The central coordinator that manages stream lifecycles, request correlation, and response handling. | RpcDispatcher extensions/muxio-rpc-service-caller/src/caller_interface.rs28 |
| Endpoint | A registry for RPC method handlers. It maps method_id to asynchronous logic. | RpcServiceEndpoint extensions/muxio-rpc-service-endpoint/src/endpoint.rs:1-10 |
| Frame | The smallest unit of data transmission, containing a header and a payload chunk. | Frame muxio-core/src/frame/mod.rs |
| Method ID | A unique u64 identifier for an RPC function, typically generated via xxh3 hashing at compile time. | rpc_method_id! extensions/muxio-rpc-service/src/lib.rs |
| Prebuffered | A communication pattern where the entire payload (request or response) is collected into a single buffer before being passed to the handler or caller. | RpcMethodPrebuffered extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs11 |
| RPC Session | An internal state tracker that manages unique rpc_request_id allocation and stream event routing. | RpcRespondableSession muxio-core/src/rpc/mod.rs |
| Dynamic Channel | An abstraction over bounded and unbounded mpsc channels used for streaming RPC responses. | DynamicChannel extensions/muxio-rpc-service-caller/src/dynamic_channel.rs:6-10 |
Sources: extensions/muxio-rpc-service-caller/src/caller_interface.rs:25-30 extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs:11-21 extensions/muxio-rpc-service-caller/src/dynamic_channel.rs:1-10
Data Flow & Architecture Diagrams
The following diagrams illustrate how natural language concepts map to specific code entities and how data flows through the system.
Request Lifecycle: From Caller to Transport
This diagram bridges the “Natural Language Space” of making a call to the “Code Entity Space” of encoders and emitters.
graph TD
User["User Code"] -- "1. call(input)" --> RPCBP["RpcCallPrebuffered::call"]
RPCBP -- "2. encode" --> RM["RpcMethodPrebuffered::encode_request"]
RPCBP -- "3. dispatch" --> RSCI["RpcServiceCallerInterface::call_rpc_streaming"]
RSCI -- "4. init" --> DISP["RpcDispatcher (Core)"]
DISP -- "5. encode frame" --> RSE["RpcStreamEncoder"]
RSE -- "6. emit bytes" --> EMIT["RpcEmit (Callback)"]
EMIT -- "7. write" --> SOCK["Underlying Transport (Tokio/WASM)"]
subgraph "muxio-rpc-service-caller"
RPCBP
RSCI
end
subgraph "muxio-core"
DISP
RSE
end
Title: RPC Call Invocation Flow
Sources: extensions/muxio-rpc-service-caller/src/caller_interface.rs:33-89 extensions/muxio-rpc-service-caller/src/prebuffered/traits.rs:50-81
Endpoint Pipeline: From Bytes to Handler
This diagram shows the pipeline used by the RpcServiceEndpoint to process incoming data, specifically how it integrates with the WASM client.
graph LR
Bytes["&[u8] from JS/Transport"] --> Read["RpcWasmClient::read_bytes"]
subgraph "RpcServiceEndpoint::read_bytes"
Read -- "1. decode" --> DISP["RpcDispatcher::read_bytes"]
DISP -- "2. finalized" --> EP["RpcServiceEndpoint"]
EP -- "3. execute" --> Handlers["Async Prebuffered Handlers"]
Handlers -- "4. respond" --> OutBytes["Outbound Bytes (emit)"]
end
OutBytes --> JS["JS static_muxio_write_bytes"]
Title: Endpoint Read Bytes Pipeline
Sources: extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:46-55 extensions/muxio-rpc-service-endpoint/tests/prebuffered_endpoint_tests.rs:71-74
Key Abbreviations
- FFI : Foreign Function Interface. Muxio’s byte-oriented design facilitates bridging Rust with JS (via WASM) or C/C++ README.md:62-63
- ID (u32/u64) :
rpc_request_id(u32): A monotonic ID unique to a single connection session, used to correlate responses to requests.rpc_method_id(u64): A static hash identifying a specific RPC service method extensions/muxio-rpc-service-caller/src/caller_interface.rs47
- WASM : WebAssembly. Specifically refers to the
muxio-wasm-rpc-clientwhich uses a bridge to communicate with JavaScript README.md53
System State Definitions
RpcTransportState
Represents the connectivity status of a caller interface extensions/muxio-rpc-service-caller/src/transport_state.rs:1-10
- Connected : The underlying transport is active; requests can be sent extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:35-41
- Disconnected : The transport is closed. Any pending requests are failed with
ReadAfterCancelor similar extensions/muxio-tokio-rpc-client/src/rpc_client.rs:102-103
RpcStreamEvent
The internal signaling mechanism used by the RpcSession to notify the RpcDispatcher of progress extensions/muxio-rpc-service-caller/src/caller_interface.rs:123-163
- Header : New stream started; contains metadata and initial parameters extensions/muxio-rpc-service-caller/src/caller_interface.rs:124-139
- PayloadChunk : A piece of the body has arrived extensions/muxio-rpc-service-caller/src/caller_interface.rs:141-156
- End : The stream is complete.
- Error : The stream was interrupted or corrupted.
Sources: extensions/muxio-rpc-service-caller/src/caller_interface.rs:123-163 extensions/muxio-tokio-rpc-client/src/rpc_client.rs:80-108 extensions/muxio-wasm-rpc-client/src/rpc_wasm_client.rs:58-68
Dismiss
Refresh this wiki
Enter email to refresh