use std::collections::HashMap;
use std::sync::atomic::AtomicBool;
use std::sync::{Arc, Mutex};
use std::time::{Duration, Instant};
use super::{GoalId, GoalStatus, ZAction};
pub struct SafeGoalManager<A: ZAction> {
inner: Mutex<GoalManagerInternal<A>>,
}
impl<A: ZAction> SafeGoalManager<A> {
pub fn new(result_timeout: Duration, goal_timeout: Option<Duration>) -> Self {
Self {
inner: Mutex::new(GoalManagerInternal {
goals: HashMap::new(),
result_timeout,
goal_timeout,
result_futures: HashMap::new(),
}),
}
}
pub fn modify<F, R>(&self, f: F) -> R
where
F: FnOnce(&mut GoalManagerInternal<A>) -> R,
{
let mut guard = self.inner.lock().expect("Lock poisoned");
f(&mut guard)
}
pub fn read<F, R>(&self, f: F) -> R
where
F: FnOnce(&GoalManagerInternal<A>) -> R,
{
let guard = self.inner.lock().expect("Lock poisoned");
f(&guard)
}
}
type ResultSenders<A> = Vec<tokio::sync::oneshot::Sender<(<A as ZAction>::Result, GoalStatus)>>;
pub struct GoalManagerInternal<A: ZAction> {
pub goals: HashMap<GoalId, ServerGoalState<A>>,
pub result_timeout: Duration,
pub goal_timeout: Option<Duration>,
pub result_futures: HashMap<GoalId, ResultSenders<A>>,
}
pub enum ServerGoalState<A: ZAction> {
Accepted {
goal: A::Goal,
timestamp: Instant,
expires_at: Option<Instant>,
},
Executing {
goal: A::Goal,
cancel_flag: Arc<AtomicBool>,
expires_at: Option<Instant>,
},
Canceling {
goal: A::Goal,
},
Terminated {
result: A::Result,
status: GoalStatus,
timestamp: Instant,
expires_at: Option<Instant>,
},
}