add server-side config --snapshot-{days,versions}

This commit is contained in:
Dustin J. Mitchell
2021-10-06 04:01:22 +00:00
parent 74aee49107
commit 4d19ca7bdb
14 changed files with 305 additions and 91 deletions

View File

@@ -2,6 +2,7 @@
//! invariants, and so on. This does not implement the HTTP-specific portions; those
//! are in [`crate::api`]. See the protocol documentation for details.
use crate::storage::{Client, Snapshot, StorageTxn};
use crate::ServerConfig; // TODO: move here
use chrono::Utc;
use uuid::Uuid;
@@ -13,12 +14,6 @@ pub const NIL_VERSION_ID: VersionId = Uuid::nil();
/// than this will be rejected.
const SNAPSHOT_SEARCH_LEN: i32 = 5;
/// Maximum number of days between snapshots
const SNAPSHOT_DAYS: i64 = 14;
/// Maximum number of versions between snapshots
const SNAPSHOT_VERSIONS: u32 = 30;
pub(crate) type HistorySegment = Vec<u8>;
pub(crate) type ClientKey = Uuid;
pub(crate) type VersionId = Uuid;
@@ -38,6 +33,7 @@ pub(crate) enum GetVersionResult {
/// Implementation of the GetChildVersion protocol transaction
pub(crate) fn get_child_version<'a>(
mut txn: Box<dyn StorageTxn + 'a>,
_config: &ServerConfig,
client_key: ClientKey,
client: Client,
parent_version_id: VersionId,
@@ -96,10 +92,10 @@ pub(crate) enum SnapshotUrgency {
impl SnapshotUrgency {
/// Calculate the urgency for a snapshot based on its age in days
fn for_days(days: i64) -> Self {
if days >= SNAPSHOT_DAYS * 3 / 2 {
fn for_days(config: &ServerConfig, days: i64) -> Self {
if days >= config.snapshot_days * 3 / 2 {
SnapshotUrgency::High
} else if days >= SNAPSHOT_DAYS {
} else if days >= config.snapshot_days {
SnapshotUrgency::Low
} else {
SnapshotUrgency::None
@@ -107,10 +103,10 @@ impl SnapshotUrgency {
}
/// Calculate the urgency for a snapshot based on its age in versions
fn for_versions_since(versions_since: u32) -> Self {
if versions_since >= SNAPSHOT_VERSIONS * 3 / 2 {
fn for_versions_since(config: &ServerConfig, versions_since: u32) -> Self {
if versions_since >= config.snapshot_versions * 3 / 2 {
SnapshotUrgency::High
} else if versions_since >= SNAPSHOT_VERSIONS {
} else if versions_since >= config.snapshot_versions {
SnapshotUrgency::Low
} else {
SnapshotUrgency::None
@@ -121,6 +117,7 @@ impl SnapshotUrgency {
/// Implementation of the AddVersion protocol transaction
pub(crate) fn add_version<'a>(
mut txn: Box<dyn StorageTxn + 'a>,
config: &ServerConfig,
client_key: ClientKey,
client: Client,
parent_version_id: VersionId,
@@ -156,7 +153,7 @@ pub(crate) fn add_version<'a>(
let time_urgency = match client.snapshot {
None => SnapshotUrgency::High,
Some(Snapshot { timestamp, .. }) => {
SnapshotUrgency::for_days((Utc::now() - timestamp).num_days())
SnapshotUrgency::for_days(config, (Utc::now() - timestamp).num_days())
}
};
@@ -164,7 +161,7 @@ pub(crate) fn add_version<'a>(
let version_urgency = match client.snapshot {
None => SnapshotUrgency::High,
Some(Snapshot { versions_since, .. }) => {
SnapshotUrgency::for_versions_since(versions_since)
SnapshotUrgency::for_versions_since(config, versions_since)
}
};
@@ -177,6 +174,7 @@ pub(crate) fn add_version<'a>(
/// Implementation of the AddSnapshot protocol transaction
pub(crate) fn add_snapshot<'a>(
mut txn: Box<dyn StorageTxn + 'a>,
_config: &ServerConfig,
client_key: ClientKey,
client: Client,
version_id: VersionId,
@@ -261,6 +259,7 @@ pub(crate) fn add_snapshot<'a>(
/// Implementation of the GetSnapshot protocol transaction
pub(crate) fn get_snapshot<'a>(
mut txn: Box<dyn StorageTxn + 'a>,
_config: &ServerConfig,
client_key: ClientKey,
client: Client,
) -> anyhow::Result<Option<(Uuid, Vec<u8>)>> {
@@ -297,18 +296,29 @@ mod test {
#[test]
fn snapshot_urgency_for_days() {
use SnapshotUrgency::*;
assert_eq!(SnapshotUrgency::for_days(0), None);
assert_eq!(SnapshotUrgency::for_days(SNAPSHOT_DAYS), Low);
assert_eq!(SnapshotUrgency::for_days(SNAPSHOT_DAYS * 2), High);
let config = ServerConfig::default();
assert_eq!(SnapshotUrgency::for_days(&config, 0), None);
assert_eq!(
SnapshotUrgency::for_days(&config, config.snapshot_days),
Low
);
assert_eq!(
SnapshotUrgency::for_days(&config, config.snapshot_days * 2),
High
);
}
#[test]
fn snapshot_urgency_for_versions_since() {
use SnapshotUrgency::*;
assert_eq!(SnapshotUrgency::for_versions_since(0), None);
assert_eq!(SnapshotUrgency::for_versions_since(SNAPSHOT_VERSIONS), Low);
let config = ServerConfig::default();
assert_eq!(SnapshotUrgency::for_versions_since(&config, 0), None);
assert_eq!(
SnapshotUrgency::for_versions_since(SNAPSHOT_VERSIONS * 2),
SnapshotUrgency::for_versions_since(&config, config.snapshot_versions),
Low
);
assert_eq!(
SnapshotUrgency::for_versions_since(&config, config.snapshot_versions * 2),
High
);
}
@@ -325,7 +335,13 @@ mod test {
// when no snapshot exists, the first version is NotFound
let client = txn.get_client(client_key)?.unwrap();
assert_eq!(
get_child_version(txn, client_key, client, NIL_VERSION_ID)?,
get_child_version(
txn,
&ServerConfig::default(),
client_key,
client,
NIL_VERSION_ID
)?,
GetVersionResult::NotFound
);
Ok(())
@@ -353,7 +369,13 @@ mod test {
// when a snapshot exists, the first version is GONE
let client = txn.get_client(client_key)?.unwrap();
assert_eq!(
get_child_version(txn, client_key, client, NIL_VERSION_ID)?,
get_child_version(
txn,
&ServerConfig::default(),
client_key,
client,
NIL_VERSION_ID
)?,
GetVersionResult::Gone
);
Ok(())
@@ -374,7 +396,13 @@ mod test {
let client = txn.get_client(client_key)?.unwrap();
assert_eq!(
get_child_version(txn, client_key, client, parent_version_id)?,
get_child_version(
txn,
&ServerConfig::default(),
client_key,
client,
parent_version_id
)?,
GetVersionResult::NotFound
);
Ok(())
@@ -395,7 +423,13 @@ mod test {
let client = txn.get_client(client_key)?.unwrap();
assert_eq!(
get_child_version(txn, client_key, client, parent_version_id)?,
get_child_version(
txn,
&ServerConfig::default(),
client_key,
client,
parent_version_id
)?,
GetVersionResult::Gone
);
Ok(())
@@ -422,7 +456,13 @@ mod test {
let client = txn.get_client(client_key)?.unwrap();
assert_eq!(
get_child_version(txn, client_key, client, parent_version_id)?,
get_child_version(
txn,
&ServerConfig::default(),
client_key,
client,
parent_version_id
)?,
GetVersionResult::Success {
version_id,
parent_version_id,
@@ -516,7 +556,15 @@ mod test {
// try to add a child of a version other than the latest
assert_eq!(
add_version(txn, client_key, client, versions[1], vec![3, 6, 9])?.0,
add_version(
txn,
&ServerConfig::default(),
client_key,
client,
versions[1],
vec![3, 6, 9]
)?
.0,
AddVersionResult::ExpectedParentVersion(versions[2])
);
@@ -539,7 +587,14 @@ mod test {
let mut txn = storage.txn()?;
let client = txn.get_client(client_key)?.unwrap();
let result = add_version(txn, client_key, client, versions[0], vec![3, 6, 9])?;
let result = add_version(
txn,
&ServerConfig::default(),
client_key,
client,
versions[0],
vec![3, 6, 9],
)?;
av_success_check(
&storage,
@@ -563,7 +618,14 @@ mod test {
let client = txn.get_client(client_key)?.unwrap();
let parent_version_id = Uuid::nil();
let result = add_version(txn, client_key, client, parent_version_id, vec![3, 6, 9])?;
let result = add_version(
txn,
&ServerConfig::default(),
client_key,
client,
parent_version_id,
vec![3, 6, 9],
)?;
av_success_check(
&storage,
@@ -586,7 +648,14 @@ mod test {
let mut txn = storage.txn()?;
let client = txn.get_client(client_key)?.unwrap();
let result = add_version(txn, client_key, client, versions[0], vec![1, 2, 3])?;
let result = add_version(
txn,
&ServerConfig::default(),
client_key,
client,
versions[0],
vec![1, 2, 3],
)?;
av_success_check(
&storage,
@@ -610,7 +679,14 @@ mod test {
let mut txn = storage.txn()?;
let client = txn.get_client(client_key)?.unwrap();
let result = add_version(txn, client_key, client, versions[0], vec![1, 2, 3])?;
let result = add_version(
txn,
&ServerConfig::default(),
client_key,
client,
versions[0],
vec![1, 2, 3],
)?;
av_success_check(
&storage,
@@ -634,7 +710,17 @@ mod test {
let mut txn = storage.txn()?;
let client = txn.get_client(client_key)?.unwrap();
let result = add_version(txn, client_key, client, versions[49], vec![1, 2, 3])?;
let result = add_version(
txn,
&ServerConfig {
snapshot_versions: 30,
..ServerConfig::default()
},
client_key,
client,
versions[49],
vec![1, 2, 3],
)?;
av_success_check(
&storage,
@@ -664,7 +750,14 @@ mod test {
// add a snapshot for that version
let client = txn.get_client(client_key)?.unwrap();
add_snapshot(txn, client_key, client, version_id, vec![1, 2, 3])?;
add_snapshot(
txn,
&ServerConfig::default(),
client_key,
client,
version_id,
vec![1, 2, 3],
)?;
// verify the snapshot
let mut txn = storage.txn()?;
@@ -697,7 +790,14 @@ mod test {
// add a snapshot for version 1
let client = txn.get_client(client_key)?.unwrap();
add_snapshot(txn, client_key, client, version_id_1, vec![1, 2, 3])?;
add_snapshot(
txn,
&ServerConfig::default(),
client_key,
client,
version_id_1,
vec![1, 2, 3],
)?;
// verify the snapshot
let mut txn = storage.txn()?;
@@ -731,7 +831,14 @@ mod test {
// add a snapshot for unknown version
let client = txn.get_client(client_key)?.unwrap();
let version_id_unk = Uuid::new_v4();
add_snapshot(txn, client_key, client, version_id_unk, vec![1, 2, 3])?;
add_snapshot(
txn,
&ServerConfig::default(),
client_key,
client,
version_id_unk,
vec![1, 2, 3],
)?;
// verify the snapshot does not exist
let mut txn = storage.txn()?;
@@ -763,7 +870,14 @@ mod test {
// add a snapshot for the earliest of those
let client = txn.get_client(client_key)?.unwrap();
add_snapshot(txn, client_key, client, version_ids[0], vec![1, 2, 3])?;
add_snapshot(
txn,
&ServerConfig::default(),
client_key,
client,
version_ids[0],
vec![1, 2, 3],
)?;
// verify the snapshot does not exist
let mut txn = storage.txn()?;
@@ -805,7 +919,14 @@ mod test {
// add a snapshot for the earliest of those
let client = txn.get_client(client_key)?.unwrap();
add_snapshot(txn, client_key, client, version_ids[0], vec![9, 9, 9])?;
add_snapshot(
txn,
&ServerConfig::default(),
client_key,
client,
version_ids[0],
vec![9, 9, 9],
)?;
// verify the snapshot was not replaced
let mut txn = storage.txn()?;
@@ -834,7 +955,14 @@ mod test {
// add a snapshot for the nil version
let client = txn.get_client(client_key)?.unwrap();
add_snapshot(txn, client_key, client, NIL_VERSION_ID, vec![9, 9, 9])?;
add_snapshot(
txn,
&ServerConfig::default(),
client_key,
client,
NIL_VERSION_ID,
vec![9, 9, 9],
)?;
// verify the snapshot does not exist
let mut txn = storage.txn()?;
@@ -867,7 +995,7 @@ mod test {
let client = txn.get_client(client_key)?.unwrap();
assert_eq!(
get_snapshot(txn, client_key, client)?,
get_snapshot(txn, &ServerConfig::default(), client_key, client)?,
Some((snapshot_version_id, data.clone()))
);
@@ -885,7 +1013,10 @@ mod test {
txn.new_client(client_key, NIL_VERSION_ID)?;
let client = txn.get_client(client_key)?.unwrap();
assert_eq!(get_snapshot(txn, client_key, client)?, None);
assert_eq!(
get_snapshot(txn, &ServerConfig::default(), client_key, client)?,
None
);
Ok(())
}