50 lines
1.4 KiB
Rust
50 lines
1.4 KiB
Rust
// SPDX-FileCopyrightText: 2026 Stan Grams <sjg@haxx.space>
|
|
//
|
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
//! Shared retention and synchronization policy for decoder histories.
|
|
|
|
use std::collections::VecDeque;
|
|
use std::sync::{Mutex, MutexGuard};
|
|
use std::time::{Duration, Instant};
|
|
|
|
pub(crate) const HISTORY_RETENTION: Duration = Duration::from_secs(24 * 60 * 60);
|
|
|
|
/// Maximum entries per decoder history queue. Oldest entries are evicted on
|
|
/// busy channels independently of time-based pruning.
|
|
pub(crate) const MAX_HISTORY_ENTRIES: usize = 10_000;
|
|
|
|
pub(crate) fn lock_or_recover<'a, T>(mutex: &'a Mutex<T>, label: &str) -> MutexGuard<'a, T> {
|
|
mutex.lock().unwrap_or_else(|error| {
|
|
tracing::warn!(
|
|
"Mutex for {} was poisoned (prior panic); recovering with potentially inconsistent data",
|
|
label
|
|
);
|
|
error.into_inner()
|
|
})
|
|
}
|
|
|
|
pub(crate) fn enforce_capacity<T>(deque: &mut VecDeque<T>, max: usize) {
|
|
while deque.len() > max {
|
|
deque.pop_front();
|
|
}
|
|
}
|
|
|
|
/// Drop entries older than `retention` from an ordered history queue.
|
|
pub(crate) fn prune_by_age<T>(
|
|
deque: &mut VecDeque<(Instant, T)>,
|
|
retention: Duration,
|
|
now: Instant,
|
|
) {
|
|
let Some(cutoff) = now.checked_sub(retention) else {
|
|
return;
|
|
};
|
|
while let Some((timestamp, _)) = deque.front() {
|
|
if *timestamp < cutoff {
|
|
deque.pop_front();
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
}
|