use std::{sync::Arc, time::Duration};
use crate::core::{RuntimeOwner, SupervisorCore};
use crate::error::RuntimeError;
use crate::identity::TaskId;
use crate::tasks::TaskSpec;
use super::outcome::TaskWaiter;
#[derive(Clone)]
pub struct SupervisorHandle {
owner: Arc<RuntimeOwner>,
#[cfg(feature = "controller")]
controller: Option<Arc<crate::controller::Controller>>,
}
impl std::fmt::Debug for SupervisorHandle {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SupervisorHandle")
.field("core", self.owner.core())
.finish_non_exhaustive()
}
}
impl SupervisorHandle {
pub(crate) fn new(owner: Arc<RuntimeOwner>) -> Self {
Self {
owner,
#[cfg(feature = "controller")]
controller: None,
}
}
fn core(&self) -> &Arc<SupervisorCore> {
self.owner.core()
}
#[cfg(feature = "controller")]
pub(crate) fn with_controller(
mut self,
controller: Option<Arc<crate::controller::Controller>>,
) -> Self {
self.controller = controller;
self
}
pub async fn add(&self, spec: TaskSpec) -> Result<TaskId, RuntimeError> {
self.core().add_task(spec).await
}
pub async fn try_add(&self, spec: TaskSpec) -> Result<TaskId, RuntimeError> {
self.core().try_add_task(spec).await
}
pub async fn add_and_watch(
&self,
spec: TaskSpec,
) -> Result<(TaskId, TaskWaiter), RuntimeError> {
let (id, done_rx) = self.core().add_task_watched(spec).await?;
Ok((id, TaskWaiter::new(id, done_rx)))
}
pub async fn try_add_and_watch(
&self,
spec: TaskSpec,
) -> Result<(TaskId, TaskWaiter), RuntimeError> {
let (id, done_rx) = self.core().try_add_task_watched(spec).await?;
Ok((id, TaskWaiter::new(id, done_rx)))
}
pub async fn remove(&self, id: TaskId) -> Result<bool, RuntimeError> {
#[cfg(feature = "controller")]
if let Some(controller) = &self.controller {
return controller.handle().remove(id).await;
}
self.core().remove(id).await
}
pub async fn try_remove(&self, id: TaskId) -> Result<bool, RuntimeError> {
#[cfg(feature = "controller")]
if let Some(controller) = &self.controller {
return controller.handle().try_remove(id).await;
}
self.core().try_remove(id).await
}
pub async fn remove_by_label(&self, name: &str) -> Result<bool, RuntimeError> {
self.core().remove_by_label(Arc::from(name)).await
}
pub async fn try_remove_by_label(&self, name: &str) -> Result<bool, RuntimeError> {
self.core().try_remove_by_label(Arc::from(name)).await
}
pub async fn list(&self) -> Vec<(TaskId, Arc<str>)> {
self.core().list_tasks().await
}
pub async fn alive_snapshot(&self) -> Vec<Arc<str>> {
self.core().snapshot().await
}
pub async fn is_alive(&self, name: &str) -> bool {
self.core().is_alive(name).await
}
#[must_use = "inspect the returned runtime configuration"]
pub fn runtime_config(&self) -> &crate::SupervisorConfig {
self.core().runtime_config()
}
#[must_use = "inspect the returned task defaults"]
pub fn task_defaults(&self) -> &crate::TaskDefaults {
self.core().task_defaults()
}
pub async fn cancel(&self, id: TaskId) -> Result<bool, RuntimeError> {
#[cfg(feature = "controller")]
if let Some(controller) = &self.controller {
return controller.handle().cancel(id).await;
}
self.core().cancel(id).await
}
pub async fn try_cancel(&self, id: TaskId) -> Result<bool, RuntimeError> {
#[cfg(feature = "controller")]
if let Some(controller) = &self.controller {
return controller.handle().try_cancel(id).await;
}
self.core().try_cancel(id).await
}
pub async fn cancel_by_label(&self, name: &str) -> Result<bool, RuntimeError> {
self.core().cancel_by_label(Arc::from(name)).await
}
pub async fn try_cancel_by_label(&self, name: &str) -> Result<bool, RuntimeError> {
self.core().try_cancel_by_label(Arc::from(name)).await
}
pub async fn cancel_by_label_with_timeout(
&self,
name: &str,
wait_for: Duration,
) -> Result<bool, RuntimeError> {
self.core()
.cancel_by_label_with_timeout(Arc::from(name), wait_for)
.await
}
pub async fn try_cancel_by_label_with_timeout(
&self,
name: &str,
wait_for: Duration,
) -> Result<bool, RuntimeError> {
self.core()
.try_cancel_by_label_with_timeout(Arc::from(name), wait_for)
.await
}
pub async fn cancel_with_timeout(
&self,
id: TaskId,
wait_for: Duration,
) -> Result<bool, RuntimeError> {
#[cfg(feature = "controller")]
if let Some(controller) = &self.controller {
return controller.handle().cancel_with_timeout(id, wait_for).await;
}
self.core().cancel_with_timeout(id, wait_for).await
}
pub async fn try_cancel_with_timeout(
&self,
id: TaskId,
wait_for: Duration,
) -> Result<bool, RuntimeError> {
#[cfg(feature = "controller")]
if let Some(controller) = &self.controller {
return controller
.handle()
.try_cancel_with_timeout(id, wait_for)
.await;
}
self.core().try_cancel_with_timeout(id, wait_for).await
}
#[doc(alias = "graceful shutdown")]
#[doc(alias = "graceful stop")]
pub async fn shutdown(self) -> Result<(), RuntimeError> {
self.core().shutdown().await
}
#[cfg(feature = "controller")]
#[cfg_attr(docsrs, doc(cfg(feature = "controller")))]
pub fn prepare_submission(
&self,
spec: crate::controller::ControllerSpec,
) -> Result<crate::controller::PreparedSubmission, crate::controller::ControllerError> {
match &self.controller {
Some(controller) => Ok(crate::controller::PreparedSubmission::new(
controller.handle(),
spec,
)),
None => Err(crate::controller::ControllerError::NotConfigured),
}
}
#[cfg(feature = "controller")]
#[cfg_attr(docsrs, doc(cfg(feature = "controller")))]
pub async fn submit(
&self,
spec: crate::controller::ControllerSpec,
) -> Result<TaskId, crate::controller::ControllerError> {
self.prepare_submission(spec)?.submit().await
}
#[cfg(feature = "controller")]
#[cfg_attr(docsrs, doc(cfg(feature = "controller")))]
pub fn try_submit(
&self,
spec: crate::controller::ControllerSpec,
) -> Result<TaskId, crate::controller::ControllerError> {
self.prepare_submission(spec)?.try_submit()
}
#[cfg(feature = "controller")]
#[cfg_attr(docsrs, doc(cfg(feature = "controller")))]
pub async fn submit_and_watch(
&self,
spec: crate::controller::ControllerSpec,
) -> Result<(TaskId, TaskWaiter), crate::controller::ControllerError> {
self.prepare_submission(spec)?.submit_and_watch().await
}
#[cfg(feature = "controller")]
#[cfg_attr(docsrs, doc(cfg(feature = "controller")))]
pub fn try_submit_and_watch(
&self,
spec: crate::controller::ControllerSpec,
) -> Result<(TaskId, TaskWaiter), crate::controller::ControllerError> {
self.prepare_submission(spec)?.try_submit_and_watch()
}
#[cfg(feature = "controller")]
#[cfg_attr(docsrs, doc(cfg(feature = "controller")))]
pub async fn controller_snapshot(&self) -> Option<crate::controller::ControllerSnapshot> {
match &self.controller {
Some(ctrl) => Some(ctrl.snapshot().await),
None => None,
}
}
}