From 2cebb733b54025a8ba0bb51e4dc3b7b2867cb7ef Mon Sep 17 00:00:00 2001 From: ppom Date: Sat, 28 Jun 2025 12:00:00 +0200 Subject: [PATCH] WIP duplicates - change remove_trigger to remove all triggers for a Match - schedule_exec will take only_after boolean --- TODO | 9 ++++++ src/concepts/filter.rs | 2 +- src/daemon/filter/mod.rs | 62 +++++++++++++++++++++----------------- src/daemon/filter/state.rs | 23 +++++--------- 4 files changed, 51 insertions(+), 45 deletions(-) create mode 100644 TODO diff --git a/TODO b/TODO new file mode 100644 index 0000000..10bc482 --- /dev/null +++ b/TODO @@ -0,0 +1,9 @@ +Test what happens when a Filter pattern set changes (I think it's shitty) + +fix trigger only after when extend +move match logging from concepts/filter to daemon/filter + +test new treedb::helpers +test different duplicates modes +test migration +document new option diff --git a/src/concepts/filter.rs b/src/concepts/filter.rs index 7f87f66..d79be4f 100644 --- a/src/concepts/filter.rs +++ b/src/concepts/filter.rs @@ -14,7 +14,7 @@ use tracing::info; use super::parse_duration; use super::{Action, Match, Pattern, Patterns}; -#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Deserialize, Serialize)] pub enum Duplicate { #[default] #[serde(rename = "extend")] diff --git a/src/daemon/filter/mod.rs b/src/daemon/filter/mod.rs index 117bc30..420d692 100644 --- a/src/daemon/filter/mod.rs +++ b/src/daemon/filter/mod.rs @@ -89,8 +89,11 @@ impl FilterManager { let mut state = self.state.lock().unwrap(); state.clear_past_matches(now); - if let Duplicate::Ignore = self.filter.duplicate() { - if state.triggers.contains_key(&m) {} + let already_triggered = state.triggers.contains_key(&m); + + // if duplicate: ignore and already triggered, skip + if already_triggered && Duplicate::Ignore == self.filter.duplicate() { + return false; } let trigger = match self.filter.retry() { @@ -102,18 +105,19 @@ impl FilterManager { } }; - let exec = match self.filter.duplicate() { - Duplicate::Rerun => true, - Duplicate::Extend | Duplicate::Ignore => false, - }; - - if exec { + if trigger { state.remove_match(&m); state.add_trigger(m.clone(), now); - self.schedule_exec(m, now, now, &mut state, false); + if already_triggered && Duplicate::Extend == self.filter.duplicate() { + state.remove_trigger(&m); + // TODO only schedule after actions + self.schedule_exec(m, now, now, &mut state, false, only_after); + } else { + self.schedule_exec(m, now, now, &mut state, false); + } } - exec + trigger } pub fn handle_trigger( @@ -194,29 +198,31 @@ impl FilterManager { .collect::>(); for m in cloned_triggers.into_iter() { - // mutable State required here - // Remove the match from the triggers + let map = state.triggers.get(&m).unwrap().clone(); + if let Order::Flush = order { - // delete specific (Match, Time) tuple - state.remove_trigger(&mt.m, &mt.t); + state.remove_trigger(&m); } - let m = mt.m.clone(); - let pattern_status = cs.entry(m).or_default(); + for (t, remaining) in map { + if remaining > 0 { + let pattern_status = cs.entry(m.clone()).or_default(); - for action in self.filter.actions().values() { - let action_time = mt.t + action.after_duration().unwrap_or_default(); - if action_time > now { - // Insert action - pattern_status - .actions - .entry(action.name().into()) - .or_default() - .push(action_time.to_rfc3339().chars().take(19).collect()); + for action in self.filter.actions().values() { + let action_time = t + action.after_duration().unwrap_or_default(); + if action_time > now { + // Insert action + pattern_status + .actions + .entry(action.name().into()) + .or_default() + .push(action_time.to_rfc3339().chars().take(19).collect()); - // Execute the action early - if let Order::Flush = order { - exec_now(&self.exec_limit, action, mt.m.clone()); + // Execute the action early + if let Order::Flush = order { + exec_now(&self.exec_limit, action, m.clone()); + } + } } } } diff --git a/src/daemon/filter/state.rs b/src/daemon/filter/state.rs index f72b9c0..c26b6d8 100644 --- a/src/daemon/filter/state.rs +++ b/src/daemon/filter/state.rs @@ -129,21 +129,8 @@ impl State { } /// Completely remove a Match from the triggers - pub fn remove_trigger(&mut self, m: &Match, t: &Time) { - // self.triggers.remove(&MatchTime { - // m: m.clone(), - // t: *t, - // }); - self.triggers.fetch_update(m.clone(), |map| { - map.and_then(|mut map| { - map.remove(t); - if map.is_empty() { - None - } else { - Some(map) - } - }) - }); + pub fn remove_trigger(&mut self, m: &Match) { + self.triggers.remove(m); } /// Returns whether we should still execute an action for this (Match, Time) trigger @@ -152,7 +139,11 @@ impl State { if self.has_after { let mut exec_needed = false; let mt = MatchTime { m: m.clone(), t }; - let count = self.triggers.get(&mt.m).and_then(|map| map.get(&mt.t)).cloned(); + let count = self + .triggers + .get(&mt.m) + .and_then(|map| map.get(&mt.t)) + .cloned(); if let Some(count) = count { exec_needed = true; if count <= 1 {