Skip to main content

mars_agents/models/probes/
probe_refresh.rs

1//! Shared probe cache refresh semantics for pi / opencode / cursor caches.
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
4pub enum ProbeRefreshMode {
5    /// Stale usable cache → return stale and spawn detached `__refresh-probe`.
6    #[default]
7    Background,
8    /// Stale or miss → run probe in-process; never spawn background refresh.
9    Synchronous,
10    /// No probe subprocess; use disk only (stale if present, else unavailable).
11    Skip,
12}
13
14impl ProbeRefreshMode {
15    pub fn should_spawn_background_on_stale(self, mars_offline: bool) -> bool {
16        !mars_offline && self == Self::Background
17    }
18
19    pub fn should_sync_probe_on_stale(self, mars_offline: bool) -> bool {
20        !mars_offline && self == Self::Synchronous
21    }
22
23    pub fn blocks_cold_probe(self, mars_offline: bool) -> bool {
24        mars_offline || self == Self::Skip
25    }
26}
27
28#[derive(Debug, Clone, PartialEq, Eq)]
29pub enum ProbeCacheBranch<T> {
30    Hit(T),
31    Stale(T),
32    Unavailable,
33    SynchronousProbe,
34}
35
36pub fn resolve_probe_cache_branch<Entry, Result, CachedResult, IsFresh, TriggerBackground>(
37    cached: Option<Entry>,
38    mars_offline: bool,
39    probe_refresh: ProbeRefreshMode,
40    cached_result: CachedResult,
41    is_fresh: IsFresh,
42    trigger_background: TriggerBackground,
43) -> ProbeCacheBranch<Result>
44where
45    Result: Clone,
46    CachedResult: Fn(&Entry) -> Option<&Result>,
47    IsFresh: Fn(&Entry) -> bool,
48    TriggerBackground: FnOnce(),
49{
50    if let Some(entry) = cached
51        && let Some(result) = cached_result(&entry)
52    {
53        if is_fresh(&entry) {
54            return ProbeCacheBranch::Hit(result.clone());
55        }
56        if probe_refresh.should_sync_probe_on_stale(mars_offline) {
57            return ProbeCacheBranch::SynchronousProbe;
58        }
59        let result = result.clone();
60        if probe_refresh.should_spawn_background_on_stale(mars_offline) {
61            trigger_background();
62        }
63        return ProbeCacheBranch::Stale(result);
64    }
65
66    if probe_refresh.blocks_cold_probe(mars_offline) {
67        ProbeCacheBranch::Unavailable
68    } else {
69        ProbeCacheBranch::SynchronousProbe
70    }
71}