Apply snapshots automatically on empty taskdbs
This commit is contained in:
@@ -70,7 +70,6 @@ impl SnapshotTasks {
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
/// Generate a snapshot (compressed, unencrypted) for the current state of the taskdb in the given
|
||||
/// storage.
|
||||
pub(super) fn make_snapshot(txn: &mut dyn StorageTxn) -> anyhow::Result<Vec<u8>> {
|
||||
@@ -78,7 +77,6 @@ pub(super) fn make_snapshot(txn: &mut dyn StorageTxn) -> anyhow::Result<Vec<u8>>
|
||||
all_tasks.encode()
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
/// Apply the given snapshot (compressed, unencrypted) to the taskdb's storage.
|
||||
pub(super) fn apply_snapshot(
|
||||
txn: &mut dyn StorageTxn,
|
||||
@@ -87,14 +85,8 @@ pub(super) fn apply_snapshot(
|
||||
) -> anyhow::Result<()> {
|
||||
let all_tasks = SnapshotTasks::decode(snapshot)?;
|
||||
|
||||
// first, verify that the taskdb truly is empty
|
||||
let mut empty = true;
|
||||
empty = empty && txn.all_tasks()?.is_empty();
|
||||
empty = empty && txn.get_working_set()? == vec![None];
|
||||
empty = empty && txn.base_version()? == Uuid::nil();
|
||||
empty = empty && txn.operations()?.is_empty();
|
||||
|
||||
if !empty {
|
||||
// double-check emptiness
|
||||
if !txn.is_empty()? {
|
||||
anyhow::bail!("Cannot apply snapshot to a non-empty task database");
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,15 @@ pub(super) fn sync(
|
||||
txn: &mut dyn StorageTxn,
|
||||
avoid_snapshots: bool,
|
||||
) -> anyhow::Result<()> {
|
||||
// if this taskdb is entirely empty, then start by getting and applying a snapshot
|
||||
if txn.is_empty()? {
|
||||
trace!("storage is empty; attempting to apply a snapshot");
|
||||
if let Some((version, snap)) = server.get_snapshot()? {
|
||||
snapshot::apply_snapshot(txn, version, snap.as_ref())?;
|
||||
trace!("applied snapshot for version {}", version);
|
||||
}
|
||||
}
|
||||
|
||||
// retry synchronizing until the server accepts our version (this allows for races between
|
||||
// replicas trying to sync to the same server). If the server insists on the same base
|
||||
// version twice, then we have diverged.
|
||||
@@ -293,24 +302,23 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sync_adds_snapshot() -> anyhow::Result<()> {
|
||||
let test_server = TestServer::new();
|
||||
fn test_sync_add_snapshot_start_with_snapshot() -> anyhow::Result<()> {
|
||||
let mut test_server = TestServer::new();
|
||||
|
||||
let mut server: Box<dyn Server> = test_server.server();
|
||||
let mut db1 = newdb();
|
||||
|
||||
let uuid = Uuid::new_v4();
|
||||
db1.apply(Operation::Create { uuid }).unwrap();
|
||||
db1.apply(Operation::Create { uuid })?;
|
||||
db1.apply(Operation::Update {
|
||||
uuid,
|
||||
property: "title".into(),
|
||||
value: Some("my first task".into()),
|
||||
timestamp: Utc::now(),
|
||||
})
|
||||
.unwrap();
|
||||
})?;
|
||||
|
||||
test_server.set_snapshot_urgency(SnapshotUrgency::High);
|
||||
sync(&mut server, db1.storage.txn()?.as_mut(), false).unwrap();
|
||||
sync(&mut server, db1.storage.txn()?.as_mut(), false)?;
|
||||
|
||||
// assert that a snapshot was added
|
||||
let base_version = db1.storage.txn()?.base_version()?;
|
||||
@@ -322,6 +330,26 @@ mod test {
|
||||
let tasks = SnapshotTasks::decode(&s)?.into_inner();
|
||||
assert_eq!(tasks[0].0, uuid);
|
||||
|
||||
// update the taskdb and sync again
|
||||
db1.apply(Operation::Update {
|
||||
uuid,
|
||||
property: "title".into(),
|
||||
value: Some("my first task, updated".into()),
|
||||
timestamp: Utc::now(),
|
||||
})?;
|
||||
sync(&mut server, db1.storage.txn()?.as_mut(), false)?;
|
||||
|
||||
// delete the first version, so that db2 *must* initialize from
|
||||
// the snapshot
|
||||
test_server.delete_version(Uuid::nil());
|
||||
|
||||
// sync to a new DB and check that we got the expected results
|
||||
let mut db2 = newdb();
|
||||
sync(&mut server, db2.storage.txn()?.as_mut(), false)?;
|
||||
|
||||
let task = db2.get_task(uuid)?.unwrap();
|
||||
assert_eq!(task.get("title").unwrap(), "my first task, updated");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user