1use std::{
2 future::Future,
3 io, mem,
4 pin::Pin,
5 task::{Context, Poll},
6 thread,
7 time::Duration,
8};
9
10use actix_rt::{time::sleep, System};
11use futures_core::{future::BoxFuture, Stream};
12use futures_util::stream::StreamExt as _;
13use tokio::sync::{mpsc::UnboundedReceiver, oneshot, watch};
14use tracing::{error, info};
15
16use crate::{
17 accept::Accept,
18 builder::ServerBuilder,
19 join_all::join_all,
20 service::InternalServiceFactory,
21 signals::{OsSignals, SignalKind, StopSignal},
22 waker_queue::{WakerInterest, WakerQueue},
23 worker::{ServerWorker, ServerWorkerConfig, WorkerHandleServer},
24 ServerHandle,
25};
26
27#[derive(Debug)]
28pub(crate) enum ServerCommand {
29 WorkerFaulted(usize),
33
34 Pause(oneshot::Sender<()>),
38
39 Resume(oneshot::Sender<()>),
43
44 Stop {
46 graceful: bool,
48
49 completion: Option<oneshot::Sender<()>>,
51
52 force_system_stop: bool,
54 },
55}
56
57#[must_use = "Server does nothing unless you `.await` or poll it"]
125pub struct Server {
126 handle: ServerHandle,
127 fut: BoxFuture<'static, io::Result<()>>,
128}
129
130impl Server {
131 pub fn build() -> ServerBuilder {
133 ServerBuilder::default()
134 }
135
136 pub(crate) fn new(builder: ServerBuilder) -> Self {
137 Server {
138 handle: ServerHandle::new(builder.cmd_tx.clone()),
139 fut: Box::pin(ServerInner::run(builder)),
140 }
141 }
142
143 pub fn handle(&self) -> ServerHandle {
147 self.handle.clone()
148 }
149}
150
151impl Future for Server {
152 type Output = io::Result<()>;
153
154 #[inline]
155 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
156 Pin::new(&mut Pin::into_inner(self).fut).poll(cx)
157 }
158}
159
160pub struct ServerInner {
161 worker_handles: Vec<WorkerHandleServer>,
162 accept_handle: Option<thread::JoinHandle<()>>,
163 worker_config: ServerWorkerConfig,
164 services: Vec<Box<dyn InternalServiceFactory>>,
165 waker_queue: WakerQueue,
166 system_stop: bool,
167 stopping: bool,
168 graceful_shutdown_tx: watch::Sender<()>,
169}
170
171impl ServerInner {
172 async fn run(builder: ServerBuilder) -> io::Result<()> {
173 let (mut this, mut mux) = Self::run_sync(builder)?;
174
175 while let Some(cmd) = mux.next().await {
176 this.handle_cmd(cmd).await;
177
178 if this.stopping {
179 break;
180 }
181 }
182
183 Ok(())
184 }
185
186 fn run_sync(mut builder: ServerBuilder) -> io::Result<(Self, ServerEventMultiplexer)> {
187 let is_actix = actix_rt::System::try_current().is_some();
189 let is_tokio = tokio::runtime::Handle::try_current().is_ok();
190
191 match (is_actix, is_tokio) {
192 (true, _) => info!("Actix runtime found; starting in Actix runtime"),
193 (_, true) => info!("Tokio runtime found; starting in existing Tokio runtime"),
194 (_, false) => panic!("Actix or Tokio runtime not found; halting"),
195 }
196
197 for (_, name, lst) in &builder.sockets {
198 info!(
199 r#"starting service: "{}", workers: {}, listening on: {}"#,
200 name,
201 builder.threads,
202 lst.local_addr()
203 );
204 }
205
206 let sockets = mem::take(&mut builder.sockets)
207 .into_iter()
208 .map(|t| (t.0, t.2))
209 .collect();
210
211 let (waker_queue, worker_handles, accept_handle) = Accept::start(sockets, &builder)?;
212
213 let mux = ServerEventMultiplexer {
214 signal_fut: builder.shutdown_signal.map(StopSignal::Cancel).or_else(|| {
215 builder
216 .listen_os_signals
217 .then(OsSignals::new)
218 .map(StopSignal::Os)
219 }),
220 cmd_rx: builder.cmd_rx,
221 };
222
223 let server = ServerInner {
224 waker_queue,
225 accept_handle: Some(accept_handle),
226 worker_handles,
227 worker_config: builder.worker_config,
228 services: builder.factories,
229 system_stop: builder.exit,
230 stopping: false,
231 graceful_shutdown_tx: builder.graceful_shutdown_tx,
232 };
233
234 Ok((server, mux))
235 }
236
237 async fn handle_cmd(&mut self, item: ServerCommand) {
238 match item {
239 ServerCommand::Pause(tx) => {
240 self.waker_queue.wake(WakerInterest::Pause);
241 let _ = tx.send(());
242 }
243
244 ServerCommand::Resume(tx) => {
245 self.waker_queue.wake(WakerInterest::Resume);
246 let _ = tx.send(());
247 }
248
249 ServerCommand::Stop {
250 graceful,
251 completion,
252 force_system_stop,
253 } => {
254 self.stopping = true;
255
256 if graceful {
257 self.graceful_shutdown_tx.send_replace(());
258 }
259
260 self.waker_queue.wake(WakerInterest::Stop);
263
264 let workers_stop = self
266 .worker_handles
267 .iter()
268 .map(|worker| worker.stop(graceful))
269 .collect::<Vec<_>>();
270
271 if graceful {
272 let _ = join_all(workers_stop).await;
274 }
275
276 self.accept_handle
278 .take()
279 .unwrap()
280 .join()
281 .expect("Accept thread must not panic in any case");
282
283 if let Some(tx) = completion {
284 let _ = tx.send(());
285 }
286
287 if self.system_stop || force_system_stop {
288 sleep(Duration::from_millis(300)).await;
289 System::try_current().as_ref().map(System::stop);
290 }
291 }
292
293 ServerCommand::WorkerFaulted(idx) => {
294 assert!(self.worker_handles.iter().any(|wrk| wrk.idx == idx));
296
297 error!("worker {} has died; restarting", idx);
298
299 let factories = self
300 .services
301 .iter()
302 .map(|service| service.clone_factory())
303 .collect();
304
305 match ServerWorker::start(
306 idx,
307 factories,
308 self.waker_queue.clone(),
309 self.worker_config,
310 ) {
311 Ok((handle_accept, handle_server)) => {
312 *self
313 .worker_handles
314 .iter_mut()
315 .find(|wrk| wrk.idx == idx)
316 .unwrap() = handle_server;
317
318 self.waker_queue.wake(WakerInterest::Worker(handle_accept));
319 }
320
321 Err(err) => error!("can not restart worker {}: {}", idx, err),
322 };
323 }
324 }
325 }
326
327 fn map_signal(signal: SignalKind) -> ServerCommand {
328 match signal {
329 SignalKind::Cancel => {
330 info!("Cancellation token/channel received; starting graceful shutdown");
331 ServerCommand::Stop {
332 graceful: true,
333 completion: None,
334 force_system_stop: true,
335 }
336 }
337
338 SignalKind::OsInt => {
339 info!("SIGINT received; starting forced shutdown");
340 ServerCommand::Stop {
341 graceful: false,
342 completion: None,
343 force_system_stop: true,
344 }
345 }
346
347 SignalKind::OsTerm => {
348 info!("SIGTERM received; starting graceful shutdown");
349 ServerCommand::Stop {
350 graceful: true,
351 completion: None,
352 force_system_stop: true,
353 }
354 }
355
356 SignalKind::OsQuit => {
357 info!("SIGQUIT received; starting forced shutdown");
358 ServerCommand::Stop {
359 graceful: false,
360 completion: None,
361 force_system_stop: true,
362 }
363 }
364 }
365 }
366}
367
368struct ServerEventMultiplexer {
369 cmd_rx: UnboundedReceiver<ServerCommand>,
370 signal_fut: Option<StopSignal>,
371}
372
373impl Stream for ServerEventMultiplexer {
374 type Item = ServerCommand;
375
376 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
377 let this = Pin::into_inner(self);
378
379 if let Some(signal_fut) = &mut this.signal_fut {
380 if let Poll::Ready(signal) = Pin::new(signal_fut).poll(cx) {
381 this.signal_fut = None;
382 return Poll::Ready(Some(ServerInner::map_signal(signal)));
383 }
384 }
385
386 this.cmd_rx.poll_recv(cx)
387 }
388}