use std::time::{Duration, SystemTime};
use serde::{Deserialize, Serialize};
pub mod registry;
pub use registry::{WorkspaceRecord, WorkspaceRegistry};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Ttl(#[serde(with = "humantime_serde")] Duration);
impl Ttl {
#[must_use]
pub const fn new(duration: Duration) -> Self {
Self(duration)
}
#[must_use]
pub const fn duration(self) -> Duration {
self.0
}
}
impl std::fmt::Display for Ttl {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", humantime::format_duration(self.0))
}
}
impl std::str::FromStr for Ttl {
type Err = humantime::DurationError;
fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
humantime::parse_duration(s).map(Self)
}
}
#[must_use]
pub fn is_expired(record: &WorkspaceRecord, ttl: &Ttl, now: SystemTime) -> bool {
now.duration_since(record.created_at)
.map(|age| age >= ttl.0)
.unwrap_or(false)
}
#[must_use]
pub fn prune<'a>(
records: &'a [WorkspaceRecord],
ttl: &Ttl,
now: SystemTime,
) -> Vec<&'a WorkspaceRecord> {
records
.iter()
.filter(|r| r.path.exists() && is_expired(r, ttl, now))
.collect()
}
#[cfg(test)]
#[path = "ttl_tests.rs"]
mod ttl_tests;
#[cfg(test)]
#[path = "prune_tests.rs"]
mod prune_tests;
#[cfg(test)]
#[path = "serde_tests.rs"]
mod serde_tests;