use std::collections::HashMap;
use std::sync::Mutex;
use crate::runtime::{RunState, RunStatus};
struct RegistryEntry {
status: RunStatus,
current_job_id: String,
user_headers: HashMap<String, String>,
cancel_requested: bool,
input_hash: Option<[u8; 32]>,
}
#[derive(Default)]
pub(crate) struct RunRegistry {
runs: Mutex<HashMap<String, RegistryEntry>>,
}
impl RunRegistry {
pub(crate) fn known_input_hash(&self, run_id: &str) -> Option<[u8; 32]> {
self.runs
.lock()
.unwrap()
.get(run_id)
.and_then(|entry| entry.input_hash)
}
pub(crate) fn current_job_id(&self, run_id: &str) -> Option<String> {
self.runs
.lock()
.unwrap()
.get(run_id)
.map(|entry| entry.current_job_id.clone())
}
pub(crate) fn insert_submitted(
&self,
run_id: &str,
job_id: &str,
user_headers: HashMap<String, String>,
input_hash: [u8; 32],
) {
self.runs.lock().unwrap().insert(
run_id.to_string(),
RegistryEntry {
status: RunStatus {
run_id: run_id.to_string(),
state: RunState::Pending,
current_step: 0,
},
current_job_id: job_id.to_string(),
user_headers,
cancel_requested: false,
input_hash: Some(input_hash),
},
);
}
pub(crate) fn status(&self, run_id: &str) -> Option<RunStatus> {
self.runs.lock().unwrap().get(run_id).map(|entry| {
let mut status = entry.status.clone();
if entry.cancel_requested {
status.state = RunState::Cancelling;
}
status
})
}
pub(crate) fn cancel_requested(&self, run_id: &str) -> bool {
self.runs
.lock()
.unwrap()
.get(run_id)
.is_some_and(|entry| entry.cancel_requested)
}
pub(crate) fn request_cancel(
&self,
run_id: &str,
) -> Option<(String, HashMap<String, String>, u32)> {
let mut runs = self.runs.lock().unwrap();
let entry = runs.get_mut(run_id)?;
entry.cancel_requested = true;
Some((
entry.current_job_id.clone(),
entry.user_headers.clone(),
entry.status.current_step,
))
}
pub(crate) fn mark_running(
&self,
run_id: &str,
step_number: u32,
job_id: &str,
user_headers: &HashMap<String, String>,
) {
let mut runs = self.runs.lock().unwrap();
match runs.get_mut(run_id) {
Some(entry) => {
entry.status.state = RunState::Running;
entry.status.current_step = step_number;
entry.current_job_id = job_id.to_string();
}
None => {
runs.insert(
run_id.to_string(),
RegistryEntry {
status: RunStatus {
run_id: run_id.to_string(),
state: RunState::Running,
current_step: step_number,
},
current_job_id: job_id.to_string(),
user_headers: user_headers.clone(),
cancel_requested: false,
input_hash: None,
},
);
}
}
}
pub(crate) fn mark_pending(&self, run_id: &str, next_step: u32, next_job_id: String) {
if let Some(entry) = self.runs.lock().unwrap().get_mut(run_id) {
entry.status.state = RunState::Pending;
entry.status.current_step = next_step;
entry.current_job_id = next_job_id;
}
}
pub(crate) fn forget(&self, run_id: &str) {
self.runs.lock().unwrap().remove(run_id);
}
#[cfg(test)]
pub(crate) fn is_empty(&self) -> bool {
self.runs.lock().unwrap().is_empty()
}
}