This commit is contained in:
Kelorastus
2026-09-16 11:42:24 +02:00
parent b7f3061be3
commit 3fdfde7043
18 changed files with 1485 additions and 21 deletions
+33
View File
@@ -142,6 +142,20 @@ fn is_name(s: &str) -> bool {
(1..=128).contains(&s.len()) && s.bytes().all(|b| b.is_ascii_alphanumeric() || matches!(b, b'_' | b'.' | b'-'))
}
/// Lower-case hyphenated uuid, as Postgres prints gen_random_uuid().
fn is_uuid(s: &str) -> bool {
s.len() == 36
&& s.bytes().enumerate().all(|(i, b)| match i {
8 | 13 | 18 | 23 => b == b'-',
_ => b.is_ascii_digit() || (b'a'..=b'f').contains(&b),
})
}
/// A Postgres xid8 in decimal.
fn is_xid(s: &str) -> bool {
(1..=20).contains(&s.len()) && s.bytes().all(|b| b.is_ascii_digit())
}
fn is_snapshot(s: &str) -> bool {
let b = s.as_bytes();
b.len() == 16
@@ -216,6 +230,13 @@ pub fn validate(manifest: &Value) -> Result<()> {
.ok_or_else(|| Error::manifest("db.snapshot must look like 20260915T101500Z"))?;
let files = entries(db.get("files"), "db.files")?;
require(!files.is_empty(), || "db.files must not be empty".into())?;
if let Some(sync) = db.get("sync") {
let db_id = sync.get("db_id").and_then(Value::as_str).is_some_and(is_uuid);
let horizon = sync.get("horizon").and_then(Value::as_str).is_some_and(is_xid);
require(db_id && horizon, || {
"db.sync must hold the DHP's db_id (a uuid) and a horizon (a transaction id)".into()
})?;
}
let prefix = format!("db/{snapshot}/");
let mut seen: HashSet<String> = HashSet::new();
for (i, entry) in files.iter().enumerate() {
@@ -328,6 +349,18 @@ pub struct DbSection {
pub schema_version: u64,
pub snapshot: String,
pub files: Vec<DbFile>,
/// Present when the snapshot comes from a DHP running operator-data sync.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sync: Option<DbSync>,
}
/// Where an install restored from this snapshot starts syncing.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct DbSync {
/// The DHP database's sync id: an install only ever syncs with the database it came from.
pub db_id: String,
/// Oldest transaction still running when the snapshot was taken; the first pull starts there.
pub horizon: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]