Skip to main content

melin_server_runtime/
lib.rs

1//! Application-agnostic LMAX-pipeline server runtime.
2//!
3//! Groups the application-agnostic parts of the Melin server: the
4//! accept loop, frame reader, ack-policy wiring, admin
5//! endpoint, replication, and the optional DPDK transport. Generic
6//! over `A: Application` — the binary supplies a concrete app via
7//! [`server::run`] (or `server::run_dpdk` under `feature = "dpdk"`) along with caller-supplied
8//! [`StartupEvents`], `RequestDecoder`, `ResponseEncoder`, and event-
9//! publisher fn.
10//!
11//! The application-side wiring (the `Application` itself, its decoder
12//! and encoder, any event publisher) lives in the application's own
13//! crate — see the examples under `crates/examples/`.
14
15pub mod ack_policy;
16pub mod admin;
17mod buf_ring;
18pub mod client_auth;
19mod client_frames;
20pub mod connection_limit;
21mod durability_gate;
22pub mod halt;
23pub mod layout;
24pub mod policy_control;
25pub mod process;
26pub mod promotion;
27mod raft;
28mod raft_promotion;
29pub mod reader;
30pub mod replication;
31pub mod response;
32mod response_frame;
33pub mod server;
34mod startup;
35#[cfg(test)]
36mod test_roles;
37mod uring_teardown;
38
39pub use startup::StartupEvents;
40
41#[cfg(feature = "dpdk")]
42pub mod dpdk_response;
43#[cfg(feature = "dpdk")]
44pub mod dpdk_transport;
45
46// The two wire bounds an application's codecs have to fit: the widest
47// request body the readers hand a decoder, and the widest response body
48// the response stages give an encoder room for — both after the
49// protocol's framing, which the runtime reads and writes itself.
50// Re-exported here so an application can assert against them at compile
51// time, next to the bounds it declares (`AppEvent::MAX_ENCODED_SIZE` is
52// the journal's; these are the wire's). `MAX_FRAME_SIZE` is the whole
53// request frame, for a program that reads client frames itself.
54pub use client_frames::{MAX_FRAME_SIZE, MAX_REQUEST_BODY};
55pub use response_frame::MAX_RESPONSE_BODY;
56
57/// Control-plane event the accept loop, reader, and response stage
58/// exchange. Transport-agnostic — the payload is a socket fd + writer,
59/// not an app event — so both build modes refer to the same type.
60pub enum ControlEvent {
61    Connected {
62        connection_id: u64,
63        fd: std::os::unix::io::RawFd,
64        writer: melin_wire_protocol::blocking::BlockingFrameWriter<Box<dyn std::io::Write + Send>>,
65    },
66    Disconnected {
67        connection_id: u64,
68    },
69    /// Reader → response: the input pipeline was full when this
70    /// connection's frame arrived; deliver a `ServerBusy` notice through
71    /// the normal egress path. Routed through the response stage so
72    /// exactly one thread ever writes a client socket — a reader-side
73    /// send could land between the two halves of a partially-flushed
74    /// response frame and permanently desync the client's length-prefix
75    /// framing (2026-08 io_uring audit, review finding F3).
76    PipelineBusy {
77        connection_id: u64,
78    },
79}