Skip to main content

rifts/
lib.rs

1//! # Rifts — Rift Realtime Protocol / 1.0 Server Implementation
2//!
3//! This crate implements the server-side of the [Rift Realtime Protocol v1.0][spec],
4//! providing an embeddable, high-performance real-time pub/sub engine.
5//!
6//! ## Core Concepts
7//!
8//! - **Broker** — the message routing core responsible for publishing,
9//!   subscribing, fan-out delivery, and replay. Ships with
10//!   [`InMemoryBroker`] (in-process) and [`RemoteBroker`] (remote TCP).
11//! - **Frame / Message** — a [`Frame`] is the wire-level transport unit
12//!   (JSON or CBOR encoded); a [`Message`] is the business-semantic layer
13//!   carried inside a frame (commands, events, datagrams, snapshots, etc.).
14//! - **Session** — each WebSocket connection maps to a [`Session`] that
15//!   manages authentication state, offset tracking, and heartbeat.
16//! - **Transport** — transport-layer abstraction with built-in adapters
17//!   for `axum`, `actix-web`, `warp`, `ntex`, plus a standalone
18//!   WebSocket listener.
19//! - **Topic Profile** — each topic can carry its own retention policy,
20//!   ordering policy, subscriber/publisher limits, snapshot toggle, etc.
21//!
22//! ## Quick Start
23//!
24//! ```no_run
25//! use rifts::RiftServer;
26//! use std::sync::Arc;
27//! use tokio::sync::Notify;
28//!
29//! # async fn run() -> rifts::Result<()> {
30//! let shutdown = Arc::new(Notify::new());
31//! let server = RiftServer::builder()
32//!     .websocket_transport()
33//!     .build()?;
34//! server.run("127.0.0.1:9000".parse().unwrap(), shutdown).await?;
35//! # Ok(()) }
36//! ```
37//!
38//! ## Module Overview (spec §30)
39//!
40//! | Module | Responsibility |
41//! |--------|----------------|
42//! | [`ack`] | Message acknowledgement (ack / nack) semantics and tracking |
43//! | [`actor`] | Actor model — each topic is managed by an independent actor |
44//! | [`broker`] | Message routing core — publish, subscribe, fan-out, dedupe |
45//! | [`codec`] | Serialization codecs (JSON / CBOR) |
46//! | [`config`] | Server configuration (payload limits, heartbeat policy, etc.) |
47//! | [`connection`] | Connection-level processing — frame parsing, dispatch, backpressure |
48//! | [`error`] | Global error type hierarchy |
49//! | [`flow`] | Flow control — backpressure, rate limiting |
50//! | [`frame`] | Protocol frame structure and codec helpers |
51//! | [`message`] | Message semantic layer (Command / Event / Datagram / Stream / Snapshot) |
52//! | [`metrics`] | Process-local metric counters (exportable to Prometheus) |
53//! | [`protocol`] | Protocol constants — handshake, heartbeat, error codes, versioning, close codes |
54//! | [`session`] | Session management — authentication, offset tracking, resume |
55//! | [`storage`] | Persistent storage engine — append log, offset index, dedupe, snapshot |
56//! | [`topic`] | Topic profile — retention policy, ordering policy, storage binding |
57//! | [`trace`] | Lightweight distributed tracing context |
58//! | [`transport`] | Transport-layer abstraction and framework adapters |
59//!
60//! [spec]: https://github.com/lazhenyi/rift-protocol
61
62#![forbid(unsafe_code)]
63#![deny(unreachable_pub)]
64#![warn(rust_2018_idioms)]
65
66// ── Module declarations ──────────────────────────────────────────────────────
67
68/// Message acknowledgement (ack / nack) semantics and tracking.
69pub mod ack;
70
71/// Actor model abstraction — ActorRef, TopicActor, ActorRegistry.
72pub mod actor;
73
74/// Message routing core — Broker trait and implementations (InMemory, Remote).
75pub mod broker;
76
77/// Serialization codecs (JSON, CBOR).
78pub mod codec;
79
80/// Server configuration structures and defaults.
81pub mod config;
82
83/// Connection-level processing — frame parsing, command dispatch, backpressure.
84pub mod connection;
85
86/// Global error type hierarchy.
87pub mod error;
88
89/// Flow control strategies — backpressure, rate limiting.
90pub mod flow;
91
92/// Protocol frame (Frame) structure and codec helpers.
93pub mod frame;
94
95/// Message semantic layer — Command, Event, Datagram, Stream, Snapshot, etc.
96pub mod message;
97
98/// Process-local metric counters.
99pub mod metrics;
100
101/// Protocol constants — handshake, heartbeat, error codes, versioning, close codes.
102pub mod protocol;
103
104/// Server entry point — `RiftServer` and its Builder.
105pub mod server;
106
107/// Session management — authentication, offset tracking, resume.
108pub mod session;
109
110/// Persistent storage engine.
111pub mod storage;
112
113/// Topic profile — retention policy, ordering policy, storage.
114pub mod topic;
115
116/// Lightweight distributed tracing context.
117pub mod trace;
118
119/// Transport-layer abstraction and framework adapters.
120pub mod transport;
121
122// ── Public API re-exports ────────────────────────────────────────────────────
123
124pub use broker::{Broker, InMemoryBroker, PublishOutcome, SubscribeIntent};
125pub use config::{CodecOffer, DefaultTopicProfile, ServerConfig};
126pub use error::{BoxedStdError, ConfigError, Result, RiftError};
127pub use frame::{Codec, Frame, FrameFlags, FrameType, Priority};
128pub use message::{DeliveryMode, Message, MessageClass, SubscribeMode, SubscribeResult};
129pub use metrics::Metrics;
130pub use protocol::close::CloseCode;
131pub use protocol::error_code::ErrorCode;
132pub use protocol::hello::{AuthMode, Hello, Ready, ResumeResult, SdkInfo, Welcome};
133pub use server::{RiftServer, RiftServerBuilder};
134pub use session::{
135    AllowAllAuth, AuthContext, AuthHints, AuthProvider, ClientId, OffsetTracker, Session,
136    SessionId, SessionState, TokenAuth,
137};
138pub use topic::{OrderingPolicy, RetentionPolicy, TopicProfile, TopicStore};
139pub use transport::frame_codec::{decode_binary_frame, decode_text_frame, encode_frame};
140#[cfg(feature = "websocket")]
141pub use transport::websocket::WebSocketTransport;
142pub use transport::{Transport, TransportConnection, TransportListener};
143
144// ── Shared utilities ─────────────────────────────────────────────────────────
145
146/// Returns the current UTC time as milliseconds since the Unix epoch.
147///
148/// # Overflow Handling
149///
150/// Returns `0` when the system clock is before the Unix epoch (extremely
151/// rare but theoretically possible). This is a deliberate design choice:
152/// `0` is always stale, so any caller that checks freshness will treat
153/// it as "expired", keeping behaviour safe.
154///
155/// # Use Cases
156///
157/// - Message timestamp fields (`created_at`)
158/// - Session expiry checks
159/// - Dedupe window checks
160/// - Heartbeat timeout detection
161///
162/// **Important**: protocol-critical paths must not depend on the absolute
163/// accuracy of this value — it reflects the server's local clock and may
164/// drift from client clocks.
165pub(crate) fn now_ms() -> i64 {
166    std::time::SystemTime::now()
167        .duration_since(std::time::UNIX_EPOCH)
168        .map(|d| d.as_millis() as i64)
169        .unwrap_or(0)
170}