Skip to main content

dynomite/net/
mod.rs

1//! Connection state machines and transport listeners.
2//!
3//! This module wires together the I/O substrate from
4//! [`crate::io`], the message model from [`crate::msg`], and the
5//! protocol codecs in [`crate::proto`] into a runtime that:
6//!
7//! * accepts client connections through a [`proxy::Proxy`] listener,
8//! * accepts inbound peer connections through a
9//!   [`dnode_proxy::DnodeProxy`] listener,
10//! * fans out to backend datastores through a per-pool
11//!   [`pool::ConnPool`] of outbound [`server::ServerConn`]s,
12//! * fans out to peer nodes through a
13//!   [`dnode_server::DnodeServerConn`] outbound connection,
14//! * tracks consecutive-failure auto-eject decisions via
15//!   [`auto_eject::AutoEject`].
16//!
17//! Every connection holds a boxed
18//! [`Transport`](crate::io::reactor::Transport) so the same FSM
19//! drives TCP today and QUIC behind the `quic` cargo feature.
20//!
21//! Cluster routing decisions (request forwarding across racks /
22//! DCs, peer selection, gossip) live in Stage 10's `cluster::*`
23//! module and are dispatched into via the [`Dispatcher`] trait
24//! below.
25//!
26//! # Examples
27//!
28//! ```no_run
29//! use dynomite::net::{ConnPool, ConnPoolConfig};
30//! # use dynomite::io::reactor::ConnRole;
31//! # use dynomite::io::reactor::TcpTransport;
32//! # use std::time::Duration;
33//! # async fn demo() -> std::io::Result<()> {
34//! let cfg = ConnPoolConfig {
35//!     max_connections: 4,
36//!     server_failure_limit: 3,
37//!     server_retry_timeout_ms: 1_000,
38//!     auto_eject: true,
39//! };
40//! let pool: ConnPool<TcpTransport> = ConnPool::new(cfg);
41//! assert_eq!(pool.config().max_connections, 4);
42//! # Ok(())
43//! # }
44//! ```
45
46pub mod auto_eject;
47pub mod client;
48pub mod conn;
49pub mod dispatcher;
50pub mod dnode_client;
51pub mod dnode_proxy;
52pub mod dnode_server;
53pub mod listener;
54pub mod pool;
55pub mod proxy;
56pub mod server;
57pub mod tls;
58
59#[cfg(feature = "quic")]
60pub mod quic;
61
62use std::io;
63
64use thiserror::Error;
65
66pub use self::auto_eject::{AutoEject, AutoEjectState};
67pub use self::client::{ClientHandler, ClientLoopOutcome};
68pub use self::conn::{Conn, ConnHandle, ConnStats};
69pub use self::dispatcher::{
70    DispatchOutcome, Dispatcher, NoopDispatcher, OutboundEnvelope, ServerSink,
71};
72pub use self::dnode_client::DnodeClientHandler;
73pub use self::dnode_proxy::DnodeProxy;
74pub use self::dnode_server::DnodeServerConn;
75pub use self::listener::{bind_dual_stack, BindOptions};
76pub use self::pool::{ConnFactory, ConnHandle as PoolHandle, ConnPool, ConnPoolConfig};
77pub use self::proxy::Proxy;
78pub use self::server::ServerConn;
79pub use self::tls::{
80    acceptor_from, connector_from, load_client_config, load_server_config, server_name_owned,
81    SharedTlsProfiles, TlsClientTransport, TlsError, TlsServerTransport,
82};
83
84/// Top-level error type returned by net::* operations.
85#[derive(Debug, Error)]
86pub enum NetError {
87    /// I/O error from the transport layer.
88    #[error("io error: {0}")]
89    Io(#[from] io::Error),
90    /// Protocol parsing error reported by a datastore codec.
91    #[error("protocol parse error: {0}")]
92    Parse(String),
93    /// DNODE codec error.
94    #[error("dnode error: {0}")]
95    Dnode(String),
96    /// The pool exhausted its retry budget for a server.
97    #[error("server has been auto-ejected")]
98    Ejected,
99    /// The pool reached its maximum connection count and there is
100    /// no idle handle to return.
101    #[error("connection pool exhausted")]
102    PoolExhausted,
103    /// The pool was shut down while a caller was waiting for a
104    /// handle.
105    #[error("connection pool shut down")]
106    PoolShutdown,
107    /// Connection closed while operation was in flight.
108    #[error("connection closed")]
109    Closed,
110    /// TLS-handshake or load-time error.
111    #[error("tls error: {0}")]
112    Tls(String),
113}
114
115impl From<crate::net::tls::TlsError> for NetError {
116    fn from(value: crate::net::tls::TlsError) -> Self {
117        NetError::Tls(value.to_string())
118    }
119}
120
121impl From<crate::proto::dnode::DnodeError> for NetError {
122    fn from(value: crate::proto::dnode::DnodeError) -> Self {
123        NetError::Dnode(format!("{value:?}"))
124    }
125}