Skip to main content

rs_zero/core/
service.rs

1use std::{future::Future, net::SocketAddr, pin::Pin};
2
3use crate::core::{CoreResult, ShutdownToken};
4
5/// Common service identity used by REST and RPC runtimes.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct ServiceInfo {
8    /// Logical service name.
9    pub name: String,
10    /// Bound address.
11    pub addr: SocketAddr,
12}
13
14impl ServiceInfo {
15    /// Creates a service identity.
16    pub fn new(name: impl Into<String>, addr: SocketAddr) -> Self {
17        Self {
18            name: name.into(),
19            addr,
20        }
21    }
22}
23
24/// Boxed future returned by [`Service`] lifecycle methods.
25pub type ServiceFuture<'a> = Pin<Box<dyn Future<Output = CoreResult<()>> + Send + 'a>>;
26
27/// Async service lifecycle managed by [`crate::core::ServiceGroup`].
28///
29/// Implementors should return from [`Service::start`] when the supplied
30/// [`ShutdownToken`] is cancelled. [`Service::stop`] is a best-effort hook used
31/// to unblock resources that do not observe the token directly.
32pub trait Service: Send + Sync + 'static {
33    /// Logical service name used in logs and error messages.
34    fn name(&self) -> &str;
35
36    /// Starts the service and runs until shutdown or failure.
37    fn start(&self, shutdown: ShutdownToken) -> ServiceFuture<'_>;
38
39    /// Stops the service. The default implementation is a no-op.
40    fn stop(&self) -> ServiceFuture<'_> {
41        Box::pin(async { Ok(()) })
42    }
43}
44
45/// Async service backed by a start function.
46pub struct FnService<F> {
47    name: String,
48    start: F,
49}
50
51impl<F> FnService<F> {
52    /// Creates a function-backed service.
53    pub fn new(name: impl Into<String>, start: F) -> Self {
54        Self {
55            name: name.into(),
56            start,
57        }
58    }
59}
60
61impl<F, Fut> Service for FnService<F>
62where
63    F: Fn(ShutdownToken) -> Fut + Send + Sync + 'static,
64    Fut: Future<Output = CoreResult<()>> + Send + 'static,
65{
66    fn name(&self) -> &str {
67        &self.name
68    }
69
70    fn start(&self, shutdown: ShutdownToken) -> ServiceFuture<'_> {
71        Box::pin((self.start)(shutdown))
72    }
73}