#![allow(unreachable_pub)]
use std::time::Duration;
use temporalio_macros::{workflow, workflow_methods};
use temporalio_sdk::{SyncWorkflowContext, WorkflowContext, WorkflowContextView, WorkflowResult};
#[workflow]
pub struct UpdatableTimerWorkflow {
deadline_ms: u64,
deadline_version: u64,
}
#[workflow_methods]
impl UpdatableTimerWorkflow {
#[init]
pub fn new(_ctx: &WorkflowContextView, initial_deadline_ms: u64) -> Self {
Self {
deadline_ms: initial_deadline_ms,
deadline_version: 0,
}
}
#[run]
pub async fn run(ctx: &mut WorkflowContext<Self>) -> WorkflowResult<String> {
loop {
let current_version = ctx.state(|s| s.deadline_version);
let deadline_ms = ctx.state(|s| s.deadline_ms);
let now_ms = ctx
.workflow_time()
.ok_or_else(|| anyhow::anyhow!("Did not find workflow time"))?
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_millis() as u64;
if deadline_ms <= now_ms {
return Ok(format!("Timer fired at deadline {deadline_ms}"));
}
let remaining = Duration::from_millis(deadline_ms - now_ms);
temporalio_sdk::workflows::select! {
_ = ctx.timer(remaining) => {
let final_deadline = ctx.state(|s| s.deadline_ms);
return Ok(format!("Timer fired at deadline {final_deadline}"));
}
_ = ctx.wait_condition(|s: &Self| s.deadline_version != current_version) => {
}
}
}
}
#[signal]
pub fn update_deadline(&mut self, _ctx: &mut SyncWorkflowContext<Self>, new_deadline_ms: u64) {
self.deadline_ms = new_deadline_ms;
self.deadline_version += 1;
}
#[query]
pub fn get_deadline(&self, _ctx: &WorkflowContextView) -> u64 {
self.deadline_ms
}
}