use std::path::Path;
use crate::contracts::{QueueFile, SessionState, TaskStatus};
use crate::timeutil;
use super::persistence::load_session;
#[allow(clippy::large_enum_variant)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum SessionValidationResult {
Valid(SessionState),
NoSession,
Stale { reason: String },
Timeout { hours: u64, session: SessionState },
}
pub fn validate_session_with_now(
session: &SessionState,
queue: &QueueFile,
timeout_hours: Option<u64>,
now: time::OffsetDateTime,
) -> SessionValidationResult {
let task = match queue
.tasks
.iter()
.find(|task| task.id.trim() == session.task_id)
{
Some(task) => task,
None => {
return SessionValidationResult::Stale {
reason: format!("Task {} no longer exists in queue", session.task_id),
};
}
};
if task.status != TaskStatus::Doing {
return SessionValidationResult::Stale {
reason: format!(
"Task {} is not in Doing status (current: {})",
session.task_id, task.status
),
};
}
if let Some(timeout) = timeout_hours
&& let Ok(session_time) = timeutil::parse_rfc3339(&session.last_updated_at)
&& now > session_time
{
let elapsed = now - session_time;
let hours = elapsed.whole_hours() as u64;
if hours >= timeout {
return SessionValidationResult::Timeout {
hours,
session: session.clone(),
};
}
}
SessionValidationResult::Valid(session.clone())
}
pub fn validate_session(
session: &SessionState,
queue: &QueueFile,
timeout_hours: Option<u64>,
) -> SessionValidationResult {
validate_session_with_now(
session,
queue,
timeout_hours,
time::OffsetDateTime::now_utc(),
)
}
pub fn check_session(
cache_dir: &Path,
queue: &QueueFile,
timeout_hours: Option<u64>,
) -> anyhow::Result<SessionValidationResult> {
let session = match load_session(cache_dir)? {
Some(session) => session,
None => return Ok(SessionValidationResult::NoSession),
};
Ok(validate_session(&session, queue, timeout_hours))
}