From e5a622844848740fd0d08e96a8955258a4901df5 Mon Sep 17 00:00:00 2001 From: Lee Smet Date: Thu, 28 Aug 2025 16:42:48 +0200 Subject: [PATCH] Periodically check the job status on the supervisor Signed-off-by: Lee Smet --- src/service.rs | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/service.rs b/src/service.rs index d1c9422..8b0a9b7 100644 --- a/src/service.rs +++ b/src/service.rs @@ -694,6 +694,48 @@ impl AppService { Ok(()) } +/// Bypass-permission variant to update a job status with transition validation. + /// This skips the executor permission check but enforces the same state transition rules. + pub async fn update_job_status_unchecked( + &self, + context_id: u32, + caller_id: u32, + id: u32, + new_status: JobStatus, + ) -> Result<(), BoxError> { + let job = self.redis.load_job(context_id, caller_id, id).await?; + let current = job.status(); + + if new_status == current { + // Idempotent: don't touch storage if no change + return Ok(()); + } + + let allowed = match current { + JobStatus::Dispatched => matches!( + new_status, + JobStatus::WaitingForPrerequisites | JobStatus::Started | JobStatus::Error + ), + JobStatus::WaitingForPrerequisites => { + matches!(new_status, JobStatus::Started | JobStatus::Error) + } + JobStatus::Started => matches!(new_status, JobStatus::Finished | JobStatus::Error), + JobStatus::Finished | JobStatus::Error => false, + }; + + if !allowed { + return Err(Box::new(InvalidJobStatusTransition { + from: current, + to: new_status, + })); + } + + self.redis + .update_job_status(context_id, caller_id, id, new_status) + .await?; + + Ok(()) + } // ----------------------------- // Message