ntex_server/pool.rs
1use ntex_util::time::Millis;
2
3use crate::{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: bool,
19}
20
21impl Default for WorkerPool {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl WorkerPool {
28 #[must_use]
29 /// Creates a worker pool with default settings.
30 pub fn new() -> Self {
31 let num = core_affinity::get_core_ids().map_or_else(
32 || std::thread::available_parallelism().map_or(2, std::num::NonZeroUsize::get),
33 |v| v.len(),
34 );
35
36 WorkerPool {
37 num,
38 name: "ntex".to_string(),
39 no_signals: false,
40 stop_runtime: false,
41 stop_on_panic: false,
42 graceful_shutdown: false,
43 graceful_shutdown_timeout: DEFAULT_SHUTDOWN_TIMEOUT,
44 affinity: false,
45 }
46 }
47
48 #[must_use]
49 /// Sets the worker thread name prefix.
50 ///
51 /// The configured name is used for worker thread names.
52 pub fn name<T: AsRef<str>>(mut self, name: T) -> Self {
53 self.name = name.as_ref().to_string();
54 self
55 }
56
57 #[must_use]
58 /// Sets the number of worker threads to start.
59 ///
60 /// By default, the server uses the number of available logical CPUs.
61 pub fn workers(mut self, num: usize) -> Self {
62 self.num = num;
63 self
64 }
65
66 #[must_use]
67 /// Stops the current ntex runtime after the server has stopped.
68 ///
69 /// By default, "stop runtime" is disabled.
70 pub fn stop_runtime(mut self) -> Self {
71 self.stop_runtime = true;
72 self
73 }
74
75 #[must_use]
76 /// Stops the server when one of the workers fails.
77 ///
78 /// A worker fails when it panics or its service cannot be created. The
79 /// stop is graceful only if [`graceful_shutdown`](Self::graceful_shutdown)
80 /// is enabled. Without this option, a failed worker is restarted.
81 ///
82 /// By default, "stop on panic" is disabled.
83 pub fn stop_on_panic(mut self) -> Self {
84 self.stop_on_panic = true;
85 self
86 }
87
88 #[must_use]
89 /// Disables signal handling.
90 ///
91 /// By default, the server stops on SIGINT, SIGTERM, and SIGQUIT.
92 pub fn disable_signals(mut self) -> Self {
93 self.no_signals = true;
94 self
95 }
96
97 #[must_use]
98 /// Enables graceful shutdown on SIGQUIT, fatal signals, and panics.
99 ///
100 /// When enabled, SIGQUIT, SIGSEGV, SIGABRT, application panics, and
101 /// worker failures with "stop on panic" stop the server gracefully.
102 /// SIGTERM always stops gracefully and SIGINT always stops immediately.
103 ///
104 /// By default, these events stop the server immediately.
105 pub fn graceful_shutdown(mut self) -> Self {
106 self.graceful_shutdown = true;
107 self
108 }
109
110 #[must_use]
111 /// Timeout for graceful worker shutdown.
112 ///
113 /// After receiving a stop signal, workers have this much time to finish
114 /// serving requests. Workers that are still alive after the timeout are
115 /// forcefully dropped.
116 ///
117 /// This bounds the worker as a whole, not an individual connection. Each
118 /// connection is bound separately by `IoConfig::set_shutdown_timeout`, so
119 /// this value should leave room for the connections a worker is still
120 /// draining to shut down themselves.
121 ///
122 /// By default, the timeout is set to 30 seconds.
123 pub fn graceful_shutdown_timeout<T: Into<Millis>>(mut self, timeout: T) -> Self {
124 self.graceful_shutdown_timeout = timeout.into();
125 self
126 }
127
128 #[must_use]
129 /// Enables CPU affinity for worker threads.
130 ///
131 /// By default, affinity is disabled.
132 pub fn enable_affinity(mut self) -> Self {
133 self.affinity = true;
134 self
135 }
136
137 /// Starts processing incoming items and returns a server controller.
138 pub fn run<F: ServerConfiguration>(self, factory: F) -> Server<F::Item> {
139 ServerManager::start(self, factory)
140 }
141}