Skip to main content

leyline/cookie/jar/
autosave.rs

1use std::path::{Path, PathBuf};
2use std::sync::Arc;
3use std::time::Duration;
4
5use crate::core::Result;
6use crate::util::autosave::{Autosave, SaveJob, SaveTarget, Schedule};
7
8use super::Jar;
9
10pub struct JarAutosave {
11    path: Arc<Path>,
12    autosave: Autosave,
13}
14
15struct JarTarget {
16    jar: Jar,
17    path: Arc<Path>,
18    saved: Option<u64>,
19}
20
21impl Jar {
22    pub fn autosave(&self, path: impl Into<PathBuf>, interval: Duration) -> JarAutosave {
23        let path: Arc<Path> = Arc::from(path.into());
24        let target = JarTarget {
25            jar: self.clone(),
26            path: Arc::clone(&path),
27            saved: None,
28        };
29        let schedule = Schedule {
30            interval,
31            periodic: None,
32            label: "cookie jar",
33        };
34        JarAutosave {
35            path,
36            autosave: Autosave::spawn(target, self.changes(), schedule),
37        }
38    }
39}
40
41impl JarAutosave {
42    pub async fn flush(&self) -> Result<()> {
43        self.autosave.flush().await
44    }
45
46    pub async fn shutdown(self) -> Result<()> {
47        self.autosave.shutdown().await
48    }
49}
50
51impl std::fmt::Debug for JarAutosave {
52    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
53        f.debug_struct("JarAutosave")
54            .field("path", &self.path)
55            .finish_non_exhaustive()
56    }
57}
58
59impl SaveTarget for JarTarget {
60    fn prepare(&mut self) -> Option<SaveJob> {
61        let generation = *self.jar.changes.borrow();
62        if self.saved == Some(generation) {
63            return None;
64        }
65        let jar = self.jar.clone();
66        let path = Arc::clone(&self.path);
67        Some(SaveJob {
68            generation,
69            write: Box::new(move || jar.save_to(&*path)),
70        })
71    }
72
73    fn saved(&mut self, generation: u64) {
74        self.saved = Some(generation);
75    }
76}