composable_runtime/service.rs
1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4
5use anyhow::Result;
6
7use crate::composition::registry::HostCapabilityFactory;
8use crate::config::types::ConfigHandler;
9use crate::types::ComponentInvoker;
10#[cfg(feature = "messaging")]
11use crate::types::MessagePublisher;
12
13/// Lifecycle-managed service that participates in config parsing and runtime.
14///
15/// A service optionally provides a `ConfigHandler` for parsing its own config
16/// categories during the build phase, `HostCapability` implementations for
17/// component linking, and `start`/`shutdown` lifecycle hooks.
18///
19/// The `config_handler()` method returns a separate handler object that can
20/// write parsed config into shared state (e.g. `Arc<Mutex<...>>`). After
21/// config processing, the handler is dropped and the service can read the
22/// accumulated state in its `capabilities()` and `start()` implementations.
23///
24/// Dependencies are injected via `set_*` methods before `start()` is called.
25/// Override only the ones your service needs; all have default no-ops.
26pub trait Service: Send + Sync {
27 /// Provide a config handler for parsing this service's config categories.
28 /// Returns `None` if the service has no config (default).
29 fn config_handler(&self) -> Option<Box<dyn ConfigHandler>> {
30 None
31 }
32
33 /// Provide any HostCapability factories to register (default is empty).
34 /// Called after config parsing and before registry build.
35 /// Each factory creates capability instances from `config.*` values,
36 /// closing over any service-internal state needed by the capability.
37 fn capabilities(&self) -> Vec<(&'static str, HostCapabilityFactory)> {
38 vec![]
39 }
40
41 /// Inject the component invoker. Called before `start()`.
42 /// Override to stash the invoker for use during the service lifecycle.
43 fn set_invoker(&self, _invoker: Arc<dyn ComponentInvoker>) {}
44
45 /// Inject the message publisher. Called before `start()`.
46 /// Override to stash the publisher for use during the service lifecycle.
47 #[cfg(feature = "messaging")]
48 fn set_publisher(&self, _publisher: Arc<dyn MessagePublisher>) {}
49
50 /// Start the service. Called after all dependencies are injected.
51 /// Implementations should spawn background tasks and return immediately.
52 fn start(&self) -> Result<()> {
53 Ok(())
54 }
55
56 /// Shutdown the service, cancelling background tasks.
57 fn shutdown(&self) -> Pin<Box<dyn Future<Output = ()> + Send + '_>> {
58 Box::pin(async {})
59 }
60}