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;
18mod client_auth;
19mod client_frames;
20pub mod halt;
21pub mod layout;
22pub mod process;
23pub mod promotion;
24mod raft;
25mod raft_promotion;
26pub mod reader;
27pub mod replication;
28pub mod response;
29mod response_frame;
30pub mod server;
31mod startup;
32mod uring_teardown;
33
34pub use startup::StartupEvents;
35
36#[cfg(feature = "dpdk")]
37pub mod dpdk_response;
38#[cfg(feature = "dpdk")]
39pub mod dpdk_transport;
40
41// The two wire bounds an application's codecs have to fit: the widest
42// request body the readers hand a decoder, and the widest response body
43// the response stages give an encoder room for — both after the
44// protocol's framing, which the runtime reads and writes itself.
45// Re-exported here so an application can assert against them at compile
46// time, next to the bounds it declares (`AppEvent::MAX_ENCODED_SIZE` is
47// the journal's; these are the wire's). `MAX_FRAME_SIZE` is the whole
48// request frame, for a program that reads client frames itself.
49pub use client_frames::{MAX_FRAME_SIZE, MAX_REQUEST_BODY};
50pub use response_frame::MAX_RESPONSE_BODY;
51
52/// Control-plane event the accept loop, reader, and response stage
53/// exchange. Transport-agnostic — the payload is a socket fd + writer,
54/// not an app event — so both build modes refer to the same type.
55pub enum ControlEvent {
56 Connected {
57 connection_id: u64,
58 fd: std::os::unix::io::RawFd,
59 writer: melin_wire_protocol::blocking::BlockingFrameWriter<Box<dyn std::io::Write + Send>>,
60 },
61 Disconnected {
62 connection_id: u64,
63 },
64 /// Reader → response: the input pipeline was full when this
65 /// connection's frame arrived; deliver a `ServerBusy` notice through
66 /// the normal egress path. Routed through the response stage so
67 /// exactly one thread ever writes a client socket — a reader-side
68 /// send could land between the two halves of a partially-flushed
69 /// response frame and permanently desync the client's length-prefix
70 /// framing (2026-08 io_uring audit, review finding F3).
71 PipelineBusy {
72 connection_id: u64,
73 },
74}