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