Skip to main content

ntex_server/
pool.rs

1use ntex_util::time::Millis;
2
3use crate::{Affinity, LoadBalancing, Server, ServerConfiguration, manager::ServerManager};
4
5const DEFAULT_SHUTDOWN_TIMEOUT: Millis = Millis::from_secs(30);
6
7#[allow(clippy::struct_excessive_bools)]
8#[derive(Debug, Clone)]
9/// Builder for a pool of server workers.
10pub struct WorkerPool {
11    pub(crate) num: usize,
12    pub(crate) name: String,
13    pub(crate) no_signals: bool,
14    pub(crate) stop_runtime: bool,
15    pub(crate) stop_on_panic: bool,
16    pub(crate) graceful_shutdown: bool,
17    pub(crate) graceful_shutdown_timeout: Millis,
18    pub(crate) affinity: Affinity,
19    pub(crate) balancing: LoadBalancing,
20}
21
22impl Default for WorkerPool {
23    fn default() -> Self {
24        Self::new()
25    }
26}
27
28impl WorkerPool {
29    #[must_use]
30    /// Creates a worker pool with default settings.
31    pub fn new() -> Self {
32        let num = crate::affinity::cpu_count();
33
34        WorkerPool {
35            num,
36            name: "ntex".to_string(),
37            no_signals: false,
38            stop_runtime: false,
39            stop_on_panic: false,
40            graceful_shutdown: false,
41            graceful_shutdown_timeout: DEFAULT_SHUTDOWN_TIMEOUT,
42            affinity: Affinity::default(),
43            balancing: LoadBalancing::IncomingCpu,
44        }
45    }
46
47    #[must_use]
48    /// Sets the worker thread name prefix.
49    ///
50    /// The configured name is used for worker thread names.
51    pub fn name<T: AsRef<str>>(mut self, name: T) -> Self {
52        self.name = name.as_ref().to_string();
53        self
54    }
55
56    #[must_use]
57    /// Sets the number of worker threads to start.
58    ///
59    /// By default, the server uses the number of available logical CPUs.
60    ///
61    /// # Panics
62    ///
63    /// Panics if `num` is zero. A server without workers would never become
64    /// ready or process anything.
65    pub fn workers(mut self, num: usize) -> Self {
66        assert!(num > 0, "Server should have at least one worker");
67        self.num = num;
68        self
69    }
70
71    #[must_use]
72    /// Stops the current ntex runtime after the server has stopped.
73    ///
74    /// By default, "stop runtime" is disabled.
75    pub fn stop_runtime(mut self) -> Self {
76        self.stop_runtime = true;
77        self
78    }
79
80    #[must_use]
81    /// Stops the server when one of the workers fails.
82    ///
83    /// A worker fails when it panics or its service cannot be created. The
84    /// stop is graceful only if [`graceful_shutdown`](Self::graceful_shutdown)
85    /// is enabled. Without this option, a failed worker is restarted.
86    ///
87    /// By default, "stop on panic" is disabled.
88    pub fn stop_on_panic(mut self) -> Self {
89        self.stop_on_panic = true;
90        self
91    }
92
93    #[must_use]
94    /// Disables signal handling.
95    ///
96    /// By default, the server stops on SIGINT, SIGTERM, and SIGQUIT.
97    pub fn disable_signals(mut self) -> Self {
98        self.no_signals = true;
99        self
100    }
101
102    #[must_use]
103    /// Enables graceful shutdown on SIGQUIT, fatal signals, and panics.
104    ///
105    /// When enabled, SIGQUIT, SIGSEGV, SIGABRT, application panics, and
106    /// worker failures with "stop on panic" stop the server gracefully.
107    /// SIGTERM always stops gracefully and SIGINT always stops immediately.
108    /// SIGSEGV and SIGABRT require runtime fatal signal handling, application
109    /// panics require runtime panic handling.
110    ///
111    /// By default, these events stop the server immediately.
112    pub fn graceful_shutdown(mut self) -> Self {
113        self.graceful_shutdown = true;
114        self
115    }
116
117    #[must_use]
118    /// Timeout for graceful worker shutdown.
119    ///
120    /// After receiving a stop signal, workers have this much time to finish
121    /// serving requests. Workers that are still alive after the timeout are
122    /// forcefully dropped.
123    ///
124    /// This bounds the worker as a whole, not an individual connection. Each
125    /// connection is bound separately by `IoConfig::set_shutdown_timeout`, so
126    /// this value should leave room for the connections a worker is still
127    /// draining to shut down themselves.
128    ///
129    /// By default, the timeout is set to 30 seconds.
130    pub fn graceful_shutdown_timeout<T: Into<Millis>>(mut self, timeout: T) -> Self {
131        self.graceful_shutdown_timeout = timeout.into();
132        self
133    }
134
135    #[must_use]
136    #[deprecated(
137        since = "4.3.0",
138        note = "affinity is enabled by default, use `affinity()` to change it"
139    )]
140    /// Does nothing, affinity is enabled by default.
141    pub fn enable_affinity(self) -> Self {
142        self
143    }
144
145    #[must_use]
146    /// Sets the CPU affinity of worker threads.
147    ///
148    /// Workers are spread over physical cores first, see [`Affinity`].
149    ///
150    /// By default, [`Affinity::Soft`] is used on Windows and
151    /// [`Affinity::Core`] on other platforms.
152    pub fn affinity(mut self, affinity: Affinity) -> Self {
153        self.affinity = affinity;
154        self
155    }
156
157    #[must_use]
158    /// Sets how items are distributed between workers.
159    ///
160    /// By default, [`LoadBalancing::IncomingCpu`] sends new items to idle
161    /// workers, which helps when connections are long-lived or their load is
162    /// uneven, and prefers the worker on the CPU that receives a connection's
163    /// network packets. [`LoadBalancing::RoundRobin`] sends them to the
164    /// workers in turn.
165    pub fn load_balancing(mut self, balancing: LoadBalancing) -> Self {
166        self.balancing = balancing;
167        self
168    }
169
170    /// Starts processing incoming items and returns a server controller.
171    pub fn run<F: ServerConfiguration>(self, factory: F) -> Server<F::Item> {
172        ServerManager::start(self, factory)
173    }
174}