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