use std::sync::Arc;
use std::time::Duration;
use crate::checkpoint::{PendingStep, StepPlacement};
use crate::error::{DurableError, Error};
use crate::sysdb::types::{Timestamp, step_names};
pub fn sleep<E>(duration: Duration) -> PendingStep<'static, (), E>
where
E: DurableError + 'static,
{
let placement = StepPlacement::here();
let built = Ok((placement.executor().map(Arc::clone), placement));
PendingStep::placed(
step_names::SLEEP,
built,
move |executor, placement| async move {
let Some((executor, (workflow_id, step_id))) = executor.zip(placement.step()) else {
tracing::debug!(
duration_ms = duration.as_millis(),
"the sleep is not checkpointed: it is outside a workflow, or inside a step"
);
tokio::time::sleep(duration).await;
return Ok(());
};
let wake_at = executor
.sysdb()
.record_sleep(workflow_id, step_id, duration)
.await
.map_err(Error::SystemDatabase)?;
let remaining = wake_at.duration_since(Timestamp::now()).unwrap_or_default();
tracing::debug!(
step_id,
remaining_ms = remaining.as_millis(),
"sleeping until the recorded wake time"
);
tokio::time::sleep(remaining).await;
Ok(())
},
)
}