leyline/cookie/jar/
autosave.rs1use 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}