use std::path::PathBuf;
use crate::{
constants::{PID_FILE_NAME, PID_LOCK_SUFFIX, STATE_FILE_NAME},
runtime,
};
pub const PROJECTS_DIR: &str = "projects";
pub const LOOSE_PROJECT_ID: &str = "__loose__";
pub const CRON_FILE_NAME: &str = "cron_state.xml";
#[derive(Debug, Clone, Default)]
pub struct StateStore {
dir: PathBuf,
}
impl StateStore {
pub fn for_project(project_id: &str) -> Self {
let id = if project_id.is_empty() {
LOOSE_PROJECT_ID
} else {
project_id
};
Self::at(runtime::state_dir().join(PROJECTS_DIR).join(id))
}
pub fn loose() -> Self {
Self::for_project(LOOSE_PROJECT_ID)
}
pub fn at(dir: PathBuf) -> Self {
Self { dir }
}
pub fn dir(&self) -> &PathBuf {
&self.dir
}
pub fn pid_path(&self) -> PathBuf {
self.dir.join(PID_FILE_NAME)
}
pub fn pid_lock_path(&self) -> PathBuf {
self.dir
.join(format!("{}{}", PID_FILE_NAME, PID_LOCK_SUFFIX))
}
pub fn state_path(&self) -> PathBuf {
self.dir.join(STATE_FILE_NAME)
}
pub fn state_lock_path(&self) -> PathBuf {
self.dir
.join(format!("{}{}", STATE_FILE_NAME, PID_LOCK_SUFFIX))
}
pub fn cron_path(&self) -> PathBuf {
self.dir.join(CRON_FILE_NAME)
}
pub fn cron_lock_path(&self) -> PathBuf {
self.dir
.join(format!("{}{}", CRON_FILE_NAME, PID_LOCK_SUFFIX))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn empty_id_maps_to_loose() {
let a = StateStore::for_project("");
let b = StateStore::loose();
assert_eq!(a.dir(), b.dir());
assert!(a.dir().ends_with(LOOSE_PROJECT_ID));
}
#[test]
fn distinct_projects_get_distinct_dirs() {
let a = StateStore::for_project("alpha");
let b = StateStore::for_project("beta");
assert_ne!(a.dir(), b.dir());
assert!(a.pid_path() != b.pid_path());
assert!(a.state_path() != b.state_path());
assert!(a.cron_path() != b.cron_path());
}
#[test]
fn paths_nest_under_project_dir() {
let s = StateStore::at(PathBuf::from("/x/projects/alpha"));
assert_eq!(s.pid_path(), PathBuf::from("/x/projects/alpha/pid.xml"));
assert_eq!(
s.pid_lock_path(),
PathBuf::from("/x/projects/alpha/pid.xml.lock")
);
assert_eq!(s.state_path(), PathBuf::from("/x/projects/alpha/state.xml"));
assert_eq!(
s.cron_path(),
PathBuf::from("/x/projects/alpha/cron_state.xml")
);
}
}