Track snapshot base lineage in Django
This commit is contained in:
@@ -55,6 +55,7 @@ def discover_snapshots(
|
||||
created += 1
|
||||
else:
|
||||
updated += 1
|
||||
resolve_base_links(host=host_config)
|
||||
|
||||
return {
|
||||
"ok": True,
|
||||
@@ -66,8 +67,15 @@ def discover_snapshots(
|
||||
|
||||
def upsert_snapshot_record(*, host: HostConfig, kind: str, snapshot_dir: Path) -> tuple[SnapshotRecord, bool]:
|
||||
meta = read_snapshot_meta(snapshot_dir)
|
||||
base_defaults = _base_defaults_from_meta(meta)
|
||||
defaults = {
|
||||
"path": str(snapshot_dir),
|
||||
**base_defaults,
|
||||
"base": _resolve_base_record(
|
||||
host=host,
|
||||
kind=base_defaults["base_kind"],
|
||||
dirname=base_defaults["base_dirname"],
|
||||
),
|
||||
"status": str(meta.get("status") or ""),
|
||||
"started_at": parse_snapshot_datetime(snapshot_dir.name, meta, "started_at"),
|
||||
"ended_at": parse_snapshot_datetime(snapshot_dir.name, meta, "ended_at"),
|
||||
@@ -81,6 +89,26 @@ def upsert_snapshot_record(*, host: HostConfig, kind: str, snapshot_dir: Path) -
|
||||
)
|
||||
|
||||
|
||||
def resolve_base_links(*, host: HostConfig | None = None) -> int:
|
||||
snapshot_qs = SnapshotRecord.objects.exclude(base_dirname="").filter(base__isnull=True)
|
||||
if host is not None:
|
||||
snapshot_qs = snapshot_qs.filter(host=host)
|
||||
|
||||
updated = 0
|
||||
for snapshot in snapshot_qs.select_related("host"):
|
||||
base = _resolve_base_record(
|
||||
host=snapshot.host,
|
||||
kind=snapshot.base_kind,
|
||||
dirname=snapshot.base_dirname,
|
||||
)
|
||||
if base is None:
|
||||
continue
|
||||
snapshot.base = base
|
||||
snapshot.save(update_fields=["base"])
|
||||
updated += 1
|
||||
return updated
|
||||
|
||||
|
||||
def infer_snapshot_kind(snapshot_path: Path) -> str:
|
||||
parent = snapshot_path.parent.name
|
||||
if parent == "scheduled":
|
||||
@@ -92,6 +120,29 @@ def infer_snapshot_kind(snapshot_path: Path) -> str:
|
||||
raise ValueError(f"Cannot infer snapshot kind from path: {snapshot_path}")
|
||||
|
||||
|
||||
def _base_defaults_from_meta(meta: dict[str, Any]) -> dict[str, Any]:
|
||||
base = meta.get("base")
|
||||
if not isinstance(base, dict):
|
||||
base = {}
|
||||
|
||||
return {
|
||||
"base_kind": _base_value(base.get("kind")),
|
||||
"base_dirname": _base_value(base.get("dirname")),
|
||||
"base_path": _base_value(base.get("path")),
|
||||
"base_snapshot_id": _base_value(base.get("id")),
|
||||
}
|
||||
|
||||
|
||||
def _base_value(value: Any) -> str:
|
||||
return value if isinstance(value, str) else ""
|
||||
|
||||
|
||||
def _resolve_base_record(*, host: HostConfig, kind: str, dirname: str) -> SnapshotRecord | None:
|
||||
if not kind or not dirname:
|
||||
return None
|
||||
return SnapshotRecord.objects.filter(host=host, kind=kind, dirname=dirname).first()
|
||||
|
||||
|
||||
def _parse_iso_z(value: str) -> datetime | None:
|
||||
try:
|
||||
if value.endswith("Z"):
|
||||
|
||||
Reference in New Issue
Block a user