isb_apps/volume_backup/
schedule.rs1use crate::jobs::RunTrigger;
4use crate::jobs::scheduler::{Entry, Scheduled};
5
6use super::{SnapshotName, VolumeBackups};
7
8impl Scheduled for VolumeBackups {
9 fn entries(&self) -> Vec<Entry> {
10 let mut out = Vec::new();
11 for org in crate::jobs::orgs(&self.inner.state) {
12 for name in self.configured(&org) {
13 let Ok(Some(r)) = self.record(&org, &name) else {
14 continue;
15 };
16 if !r.settings.enabled {
17 continue;
18 }
19 let (Ok(Some(schedule)), Ok(grace)) = (
20 r.settings.schedule(),
21 crate::jobs::parse_grace(&r.settings.missed_grace),
22 ) else {
23 continue;
24 };
25 out.push(Entry {
26 org: org.clone(),
27 name,
28 schedule,
29 anchor: r.anchor,
30 grace,
31 });
32 }
33 }
34 out
35 }
36
37 fn fire(&self, e: &Entry, slot: i64, late: bool) {
38 {
39 let _g = self.inner.edit.lock().unwrap();
40 let Ok(Some(mut r)) = self.record(&e.org, &e.name) else {
41 return;
42 };
43 if r.anchor >= slot {
44 return;
45 }
46 r.anchor = slot;
47 if let Err(err) = self.save(&e.org, &e.name, &r) {
48 eprintln!("isb serve: volume {}: {err}", e.name);
49 return;
50 }
51 }
52 let trigger = if late {
53 RunTrigger::Missed
54 } else {
55 RunTrigger::Schedule
56 };
57 let r = self.snapshot(
58 &e.org,
59 &e.name,
60 SnapshotName::Auto,
61 (trigger, "schedule", Some(slot)),
62 );
63 if let Err(err) = r {
64 let store = self.runs(&e.org, &e.name);
66 if let Ok((mut run, mut log)) =
67 store.start("snapshot", trigger, "schedule", Some(slot), 50)
68 {
69 log.line(&format!("isb: {err}"));
70 run.error = Some(err.to_string());
71 run.finish(crate::jobs::RunStatus::Failed);
72 let _ = store.finish(&mut run, &mut log);
73 }
74 self.event(
75 &e.org,
76 &e.name,
77 "volume.snapshot.failed",
78 "error",
79 format!("snapshot of {} failed: {err}", e.name),
80 );
81 }
82 }
83
84 fn advance(&self, e: &Entry, to: i64) {
85 let _g = self.inner.edit.lock().unwrap();
86 if let Ok(Some(mut r)) = self.record(&e.org, &e.name) {
87 r.anchor = to;
88 let _ = self.save(&e.org, &e.name, &r);
89 }
90 }
91}