dpm_engine/query/
advisory.rs1use dpm_model::{ActorId, Key, Plan, WorkStatus};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
8#[serde(tag = "kind", rename_all = "snake_case")]
9pub enum Advisory {
10 HoldingClaims {
12 actor: ActorId,
14 holding: Vec<Key>,
16 reason: String,
18 },
19}
20
21#[must_use]
23pub fn advisories(plan: &Plan, actor: &ActorId) -> Vec<Advisory> {
24 const HELD: [WorkStatus; 3] = [
25 WorkStatus::Claimed,
26 WorkStatus::InProgress,
27 WorkStatus::Blocked,
28 ];
29 let mut holding: Vec<Key> = plan
30 .work_items
31 .values()
32 .filter(|w| HELD.contains(&w.execution.status))
33 .filter(|w| w.execution.owner.as_ref() == Some(actor))
34 .map(|w| w.key.clone())
35 .collect();
36 if holding.is_empty() {
37 return Vec::new();
38 }
39 holding.sort_by(Key::natural_cmp);
40 let reason = format!(
41 "{actor} already holds {} claimed, started or blocked task(s); finishing, releasing or \
42 handing off held work before claiming more keeps work in progress and its aging low. \
43 Advice only: the candidates are neither filtered nor reordered",
44 holding.len()
45 );
46 vec![Advisory::HoldingClaims {
47 actor: actor.clone(),
48 holding,
49 reason,
50 }]
51}
52
53#[cfg(test)]
54mod tests;