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}