use dpm_model::{ActorId, Key, Plan, WorkStatus};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum Advisory {
HoldingClaims {
actor: ActorId,
holding: Vec<Key>,
reason: String,
},
}
#[must_use]
pub fn advisories(plan: &Plan, actor: &ActorId) -> Vec<Advisory> {
const HELD: [WorkStatus; 3] = [
WorkStatus::Claimed,
WorkStatus::InProgress,
WorkStatus::Blocked,
];
let mut holding: Vec<Key> = plan
.work_items
.values()
.filter(|w| HELD.contains(&w.execution.status))
.filter(|w| w.execution.owner.as_ref() == Some(actor))
.map(|w| w.key.clone())
.collect();
if holding.is_empty() {
return Vec::new();
}
holding.sort_by(Key::natural_cmp);
let reason = format!(
"{actor} already holds {} claimed, started or blocked task(s); finishing, releasing or \
handing off held work before claiming more keeps work in progress and its aging low. \
Advice only: the candidates are neither filtered nor reordered",
holding.len()
);
vec![Advisory::HoldingClaims {
actor: actor.clone(),
holding,
reason,
}]
}
#[cfg(test)]
mod tests;