use actionqueue_core::ids::RunId;
use crate::lease::model::{Lease, LeaseExpiry, LeaseOwner};
#[derive(Debug, Clone, PartialEq, Eq)]
#[must_use]
pub enum AcquireResult {
Acquired(Lease),
AlreadyLeased,
WrongRunSlot {
requested_run_id: RunId,
existing_run_id: RunId,
},
}
pub fn acquire(
run_id: RunId,
owner: LeaseOwner,
expiry: LeaseExpiry,
current_lease: Option<Lease>,
) -> AcquireResult {
match current_lease {
Some(existing) if existing.run_id() == run_id => AcquireResult::AlreadyLeased,
Some(existing) => AcquireResult::WrongRunSlot {
requested_run_id: run_id,
existing_run_id: existing.run_id(),
},
None => AcquireResult::Acquired(Lease::new(run_id, owner, expiry)),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn acquire_succeeds_when_no_existing_lease() {
let run_id = RunId::new();
let owner = LeaseOwner::new("worker-1");
let expiry = LeaseExpiry::at(2000);
let result = acquire(run_id, owner, expiry, None);
match result {
AcquireResult::Acquired(lease) => {
assert_eq!(lease.run_id(), run_id);
assert_eq!(lease.owner().as_str(), "worker-1");
assert_eq!(lease.expiry().expires_at(), 2000);
}
AcquireResult::AlreadyLeased => panic!("Expected acquisition to succeed"),
AcquireResult::WrongRunSlot { .. } => {
panic!("Expected acquisition to use matching run slot")
}
}
}
#[test]
fn acquire_fails_when_lease_already_active() {
let run_id = RunId::new();
let existing_lease = Lease::new(run_id, "worker-1".into(), LeaseExpiry::at(2000));
let result =
acquire(run_id, "worker-2".into(), LeaseExpiry::at(3000), Some(existing_lease));
assert_eq!(result, AcquireResult::AlreadyLeased);
}
#[test]
fn acquire_returns_rejection_on_conflict() {
let run_id = RunId::new();
let existing_lease = Lease::new(run_id, "worker-1".into(), LeaseExpiry::at(2000));
let result =
acquire(run_id, "worker-2".into(), LeaseExpiry::at(3000), Some(existing_lease));
assert_eq!(result, AcquireResult::AlreadyLeased);
}
#[test]
fn acquire_reports_wrong_run_slot_when_existing_lease_is_for_different_run() {
let requested_run_id = RunId::new();
let existing_run_id = RunId::new();
let existing_lease = Lease::new(existing_run_id, "worker-1".into(), LeaseExpiry::at(2000));
let result = acquire(
requested_run_id,
"worker-2".into(),
LeaseExpiry::at(3000),
Some(existing_lease),
);
assert_eq!(result, AcquireResult::WrongRunSlot { requested_run_id, existing_run_id });
}
}