use crate::control::handle::SupervisorHandle;
use crate::error::types::SupervisorError;
use crate::runtime::control_loop::{RuntimeControlState, run_control_loop};
use crate::shutdown::stage::ShutdownPolicy;
use crate::spec::supervisor::SupervisorSpec;
use tokio::sync::{broadcast, mpsc};
#[derive(Debug, Clone, Copy, Default)]
pub struct Supervisor;
impl Supervisor {
pub async fn start(spec: SupervisorSpec) -> Result<SupervisorHandle, SupervisorError> {
let shutdown_policy = shutdown_policy_from_spec(&spec);
Self::start_with_policy(spec, shutdown_policy).await
}
pub async fn start_with_policy(
spec: SupervisorSpec,
shutdown_policy: ShutdownPolicy,
) -> Result<SupervisorHandle, SupervisorError> {
spec.validate()?;
let (command_sender, command_receiver) = mpsc::channel(spec.control_channel_capacity);
let (event_sender, _) = broadcast::channel(spec.event_channel_capacity);
let state = RuntimeControlState::new(spec, shutdown_policy, command_sender.clone())?;
tokio::spawn(run_control_loop(
state,
command_receiver,
event_sender.clone(),
));
Ok(SupervisorHandle::new(command_sender, event_sender))
}
}
fn shutdown_policy_from_spec(spec: &SupervisorSpec) -> ShutdownPolicy {
ShutdownPolicy::new(
spec.default_shutdown_policy.graceful_timeout,
spec.default_shutdown_policy.abort_wait,
true,
)
}