Vine/Server/SpawnBindTaskWithShutdown.rs
1//! Spawn a detached tokio task that serves a tonic gRPC `Router` with
2//! graceful shutdown signalling.
3//!
4//! Uses `tonic::transport::Server::serve_with_shutdown(...)` so daemon-
5//! style embedders can drain in-flight RPCs before exiting. The simpler
6//! [`crate::Server::SpawnBindTask::Fn`] runs without a shutdown signal;
7//! both shapes are kept side-by-side so embedders pick whichever matches
8//! their lifecycle model.
9//!
10//! ## Lifecycle
11//!
12//! - The task runs until `ShutdownSignal` resolves OR the OS socket closes.
13//! - On `Ok(())` exit, dev_log marks clean shutdown.
14//! - On `Err`, dev_log captures the transport error.
15//!
16//! ## Choosing between the two helpers
17//!
18//! | Need | Helper |
19//! | ------------------------------------- | --------------------------------- |
20//! | Serve until process termination | `SpawnBindTask` |
21//! | Serve until a signal fires (recommended for daemons) | `SpawnBindTaskWithShutdown` |
22
23use std::{future::Future, net::SocketAddr};
24
25use tonic::transport::server::Router;
26
27use crate::dev_log;
28
29/// Spawn a detached tokio task that serves `Router` on `Address` until
30/// `ShutdownSignal` resolves.
31///
32/// # Parameters
33///
34/// * `ServerName` - label used in dev-log messages.
35/// * `Address` - resolved socket address (callers should run
36/// [`crate::Server::ValidateSocketAddress::Fn`] first).
37/// * `Router` - constructed tonic Router with services already added.
38/// * `ShutdownSignal` - any `Future<Output = ()> + Send + 'static`. When it
39/// resolves, the server gracefully stops accepting new connections and drains
40/// in-flight calls.
41pub fn Fn<S>(ServerName:String, Address:SocketAddr, Router:Router, ShutdownSignal:S)
42where
43 S: Future<Output = ()> + Send + 'static, {
44 tokio::spawn(async move {
45 dev_log!(
46 "grpc",
47 "[Vine::Server] Starting {} gRPC server on {} (with shutdown signal)",
48 ServerName,
49 Address
50 );
51
52 let Result_ = Router.serve_with_shutdown(Address, ShutdownSignal).await;
53
54 match Result_ {
55 Ok(_) => {
56 dev_log!("grpc", "[Vine::Server] {} server stopped cleanly", ServerName);
57 },
58
59 Err(Error) => {
60 dev_log!("grpc", "error: [Vine::Server] {} gRPC server error: {}", ServerName, Error);
61 },
62 }
63 });
64}