use std::future::{Future, IntoFuture};
use std::pin::Pin;
use std::time::Duration;
use crate::{RuntimeError, TaskId, TaskSpec, TaskWaiter};
use super::{FailFast, OwnershipTimed, Unwatched, Waiting, Watched};
use crate::core::SupervisorCore;
#[must_use = "await the default add operation or call and await `.execute()`"]
pub struct AddOperation<'a, Watch = Unwatched, Admission = Waiting> {
core: &'a SupervisorCore,
spec: TaskSpec,
watch: Watch,
_admission: Admission,
}
impl<Watch, Admission> std::fmt::Debug for AddOperation<'_, Watch, Admission>
where
Watch: std::fmt::Debug,
Admission: std::fmt::Debug,
{
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter
.debug_struct("AddOperation")
.field("spec", &self.spec)
.field("watch", &self.watch)
.field("admission", &self._admission)
.finish_non_exhaustive()
}
}
impl<'a> AddOperation<'a, Unwatched, Waiting> {
#[inline]
pub(crate) fn new(core: &'a SupervisorCore, spec: TaskSpec) -> Self {
Self {
core,
spec,
watch: Unwatched,
_admission: Waiting,
}
}
}
impl<'a, Admission> AddOperation<'a, Unwatched, Admission> {
#[inline]
pub fn watch(self) -> AddOperation<'a, Watched, Admission> {
AddOperation {
core: self.core,
spec: self.spec,
watch: Watched,
_admission: self._admission,
}
}
}
impl<'a, Watch> AddOperation<'a, Watch, Waiting> {
#[inline]
pub fn ownership_timeout(self, wait_for: Duration) -> AddOperation<'a, Watch, OwnershipTimed> {
AddOperation {
core: self.core,
spec: self.spec,
watch: self.watch,
_admission: OwnershipTimed(wait_for),
}
}
#[inline]
pub fn fail_fast(self) -> AddOperation<'a, Watch, FailFast> {
AddOperation {
core: self.core,
spec: self.spec,
watch: self.watch,
_admission: FailFast,
}
}
}
impl AddOperation<'_, Unwatched, Waiting> {
#[inline]
pub async fn execute(self) -> Result<TaskId, RuntimeError> {
self.core.add_task(self.spec).await
}
}
impl<'a> IntoFuture for AddOperation<'a, Unwatched, Waiting> {
type Output = Result<TaskId, RuntimeError>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send + 'a>>;
#[inline]
fn into_future(self) -> Self::IntoFuture {
Box::pin(self.execute())
}
}
impl AddOperation<'_, Unwatched, OwnershipTimed> {
#[inline]
pub async fn execute(self) -> Result<TaskId, RuntimeError> {
self.core
.add_task_with_ownership_timeout(self.spec, self._admission.0)
.await
}
}
impl AddOperation<'_, Unwatched, FailFast> {
#[inline]
pub async fn execute(self) -> Result<TaskId, RuntimeError> {
self.core.try_add_task(self.spec).await
}
}
impl AddOperation<'_, Watched, Waiting> {
#[inline]
pub async fn execute(self) -> Result<TaskWaiter, RuntimeError> {
let (id, receiver) = self.core.add_task_watched(self.spec).await?;
Ok(TaskWaiter::new(id, receiver))
}
}
impl AddOperation<'_, Watched, OwnershipTimed> {
#[inline]
pub async fn execute(self) -> Result<TaskWaiter, RuntimeError> {
let (id, receiver) = self
.core
.add_task_watched_with_ownership_timeout(self.spec, self._admission.0)
.await?;
Ok(TaskWaiter::new(id, receiver))
}
}
impl AddOperation<'_, Watched, FailFast> {
#[inline]
pub async fn execute(self) -> Result<TaskWaiter, RuntimeError> {
let (id, receiver) = self.core.try_add_task_watched(self.spec).await?;
Ok(TaskWaiter::new(id, receiver))
}
}