Back the catalog up daily, not only before migrations
NFR-R2 asks for the catalog to be backed up on a schedule and before schema migrations. Only the second half existed: every backup on disk was a pre-migration copy, and a library that never migrated was never backed up at all. A backup is now also taken at the end of a library sweep when the newest one is more than a day old — the moment the catalog is quiet and a day's collection and people edits have just been folded in — on its own thread and its own connection, so the copy of a 130 MB file is not spent on the UI. Whether one is due is read from the backup directory, not the catalog, so the ordinary case costs nothing. An empty catalog is skipped: there is nothing in it a rescan would not rebuild. Pruning to KEEP_BACKUPS applies as before.
This commit is contained in:
@@ -4155,6 +4155,34 @@ fn apply_zoom(window: &AppWindow, ctl: &Rc<LibraryController>, delta: i32) {
|
||||
refresh_timeline(window, catalog, ctl);
|
||||
}
|
||||
|
||||
/// TRACES: NFR-R2
|
||||
/// Take the day's catalog backup if one is due, off the UI thread.
|
||||
///
|
||||
/// Decided cheaply first — [`dr_catalog::recovery::backup_due`] reads a
|
||||
/// directory listing, not the catalog — so the ordinary case of "backed up
|
||||
/// this morning already" costs no thread and no connection.
|
||||
fn spawn_scheduled_backup(ctl: &Rc<LibraryController>) {
|
||||
let Some((conn, _)) = ctl.session.borrow().clone() else {
|
||||
return;
|
||||
};
|
||||
let catalog_path = library::catalog_path(&conn.account);
|
||||
if !dr_catalog::recovery::backup_due(&catalog_path) {
|
||||
return;
|
||||
}
|
||||
std::thread::spawn(move || {
|
||||
let catalog = match dr_catalog::Catalog::open(&catalog_path) {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
log::warn!("scheduled backup: opening the catalog: {e}");
|
||||
return;
|
||||
}
|
||||
};
|
||||
if let Err(e) = dr_catalog::recovery::backup_if_due(catalog.connection(), &catalog_path) {
|
||||
log::warn!("scheduled backup: {e}");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Push shards and the catalog to the server, and take what it has.
|
||||
///
|
||||
/// Fired after the sweep completes, when there is a finished index worth
|
||||
@@ -4445,6 +4473,14 @@ fn start_sweep(window: &AppWindow, ctl: &Rc<LibraryController>) {
|
||||
refresh_timeline(&w, catalog, &ctl_cb);
|
||||
}
|
||||
}
|
||||
// TRACES: NFR-R2
|
||||
// The scheduled backup, at the moment the catalog is
|
||||
// quietest and a day's edits have just been folded in.
|
||||
// On its own thread, with its own connection: a copy
|
||||
// of a 130 MB file is a second or two the Slint loop
|
||||
// must not spend, and it runs beside the sync below,
|
||||
// which is only a reader of the same file.
|
||||
spawn_scheduled_backup(&ctl_cb);
|
||||
// Now that indexing is complete, hand the result to the
|
||||
// server so a second device inherits it rather than
|
||||
// repeating hours of range fetches.
|
||||
|
||||
Reference in New Issue
Block a user