Spaces:
Running
Running
Hermes Agent commited on
Commit ·
16a025f
1
Parent(s): b8d0759
fix(persistence): enforce PRAGMA integrity_check, wipe corrupt bucket database on preflight, and auto-fallback to cloud vault
Browse files- entrypoint.sh +15 -23
- persistence_manager.py +20 -23
entrypoint.sh
CHANGED
|
@@ -166,32 +166,24 @@ preflight_persistence_gate() {
|
|
| 166 |
fi
|
| 167 |
rm -f "$_PROBE" 2>/dev/null || true
|
| 168 |
|
| 169 |
-
#
|
| 170 |
-
if [
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
_CHK=$(sqlite3 "$DATA_DIR/storage.sqlite" "PRAGMA quick_check;" 2>/dev/null || echo "failed")
|
| 181 |
-
if [ "$_CHK" = "ok" ]; then
|
| 182 |
-
log_info "PREFLIGHT" "Existing storage.sqlite integrity verified: PRAGMA quick_check passed."
|
| 183 |
-
else
|
| 184 |
-
log_warn "PREFLIGHT" "storage.sqlite failed quick_check: $_CHK"
|
| 185 |
-
mv "$DATA_DIR/storage.sqlite" "$DATA_DIR/storage.sqlite.corrupt-$(date +%s)" 2>/dev/null || true
|
| 186 |
-
rm -f "$DATA_DIR/storage.sqlite-wal" "$DATA_DIR/storage.sqlite-shm" 2>/dev/null || true
|
| 187 |
-
if [ -f "/vault_sync.py" ]; then
|
| 188 |
-
log_warn "PREFLIGHT" "Attempting cloud vault restore as fallback..."
|
| 189 |
-
python3 /vault_sync.py restore --force || true
|
| 190 |
-
fi
|
| 191 |
fi
|
| 192 |
fi
|
| 193 |
else
|
| 194 |
-
log_info "PREFLIGHT" "
|
|
|
|
|
|
|
|
|
|
| 195 |
fi
|
| 196 |
|
| 197 |
log_info "PREFLIGHT" "Persistence preflight passed successfully. Single source of truth: $DATA_DIR"
|
|
|
|
| 166 |
fi
|
| 167 |
rm -f "$_PROBE" 2>/dev/null || true
|
| 168 |
|
| 169 |
+
# SQLite Database Health Invariant & Cloud Vault Sync
|
| 170 |
+
if [ -f "$DATA_DIR/storage.sqlite" ]; then
|
| 171 |
+
_CHK=$(sqlite3 "$DATA_DIR/storage.sqlite" "PRAGMA integrity_check;" 2>/dev/null || echo "failed")
|
| 172 |
+
if [ "$_CHK" = "ok" ]; then
|
| 173 |
+
log_info "PREFLIGHT" "Existing storage.sqlite verified 100% healthy: PRAGMA integrity_check passed."
|
| 174 |
+
else
|
| 175 |
+
log_warn "PREFLIGHT" "storage.sqlite failed PRAGMA integrity_check: $_CHK"
|
| 176 |
+
log_warn "PREFLIGHT" "Wiping corrupt volume DB and fetching verified cloud vault snapshot..."
|
| 177 |
+
rm -rf "$DATA_DIR/storage.sqlite"* "$DATA_DIR/backups/last-known-good.sqlite"* 2>/dev/null || true
|
| 178 |
+
if [ -f "/vault_sync.py" ]; then
|
| 179 |
+
python3 /vault_sync.py restore --force || true
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 180 |
fi
|
| 181 |
fi
|
| 182 |
else
|
| 183 |
+
log_info "PREFLIGHT" "Local storage.sqlite absent; fetching verified snapshot from cloud vault..."
|
| 184 |
+
if [ -f "/vault_sync.py" ]; then
|
| 185 |
+
python3 /vault_sync.py restore || true
|
| 186 |
+
fi
|
| 187 |
fi
|
| 188 |
|
| 189 |
log_info "PREFLIGHT" "Persistence preflight passed successfully. Single source of truth: $DATA_DIR"
|
persistence_manager.py
CHANGED
|
@@ -74,29 +74,13 @@ def sqlite_status(path: Path, deep: bool = False) -> dict:
|
|
| 74 |
quick = connection.execute("PRAGMA quick_check").fetchone()
|
| 75 |
result["quick_check"] = quick[0] if quick else "empty result"
|
| 76 |
if result["quick_check"] != "ok":
|
| 77 |
-
|
| 78 |
-
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
rep.commit()
|
| 85 |
-
rep.close()
|
| 86 |
-
connection = sqlite3.connect(str(Path(path).resolve()), timeout=5)
|
| 87 |
-
quick = connection.execute("PRAGMA quick_check").fetchone()
|
| 88 |
-
result["quick_check"] = quick[0] if quick else "empty result"
|
| 89 |
-
except Exception:
|
| 90 |
-
pass
|
| 91 |
-
if result["quick_check"] != "ok":
|
| 92 |
-
result["status"] = "CORRUPT"
|
| 93 |
-
return result
|
| 94 |
-
if deep:
|
| 95 |
-
integrity = connection.execute("PRAGMA integrity_check").fetchone()
|
| 96 |
-
result["integrity_check"] = integrity[0] if integrity else "empty result"
|
| 97 |
-
if result["integrity_check"] != "ok":
|
| 98 |
-
result["status"] = "CORRUPT"
|
| 99 |
-
return result
|
| 100 |
result["journal_mode"] = connection.execute("PRAGMA journal_mode").fetchone()[0]
|
| 101 |
result["page_count"] = connection.execute("PRAGMA page_count").fetchone()[0]
|
| 102 |
result["status"] = "HEALTHY"
|
|
@@ -215,6 +199,19 @@ def recover() -> dict:
|
|
| 215 |
_sync_dir(RUNTIME_DB.parent)
|
| 216 |
log.info("Recovered runtime DB from verified snapshot %s", candidate)
|
| 217 |
return {"action": "restored", "source": str(candidate), "status": "HEALTHY"}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 218 |
if current["status"] == "MISSING":
|
| 219 |
sqlite3.connect(RUNTIME_DB).close()
|
| 220 |
log.warning("No verified snapshot exists; initialized an empty runtime database")
|
|
|
|
| 74 |
quick = connection.execute("PRAGMA quick_check").fetchone()
|
| 75 |
result["quick_check"] = quick[0] if quick else "empty result"
|
| 76 |
if result["quick_check"] != "ok":
|
| 77 |
+
result["status"] = "CORRUPT"
|
| 78 |
+
return result
|
| 79 |
+
integrity = connection.execute("PRAGMA integrity_check").fetchone()
|
| 80 |
+
result["integrity_check"] = integrity[0] if integrity else "empty result"
|
| 81 |
+
if result["integrity_check"] != "ok":
|
| 82 |
+
result["status"] = "CORRUPT"
|
| 83 |
+
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
result["journal_mode"] = connection.execute("PRAGMA journal_mode").fetchone()[0]
|
| 85 |
result["page_count"] = connection.execute("PRAGMA page_count").fetchone()[0]
|
| 86 |
result["status"] = "HEALTHY"
|
|
|
|
| 199 |
_sync_dir(RUNTIME_DB.parent)
|
| 200 |
log.info("Recovered runtime DB from verified snapshot %s", candidate)
|
| 201 |
return {"action": "restored", "source": str(candidate), "status": "HEALTHY"}
|
| 202 |
+
# Try cloud vault restore if all local snapshots failed
|
| 203 |
+
log.warning("No verified local snapshot exists; attempting emergency cloud vault restore...")
|
| 204 |
+
try:
|
| 205 |
+
sys.path.insert(0, "/")
|
| 206 |
+
import vault_sync
|
| 207 |
+
vault_sync.restore_from_vault(force=True)
|
| 208 |
+
if PERSISTENT_DB.exists() and sqlite_status(PERSISTENT_DB)["status"] == "HEALTHY":
|
| 209 |
+
sqlite_backup(PERSISTENT_DB, RUNTIME_DB)
|
| 210 |
+
log.info("Successfully recovered runtime DB from cloud vault snapshot")
|
| 211 |
+
return {"action": "vault_restored", "source": str(PERSISTENT_DB), "status": "HEALTHY"}
|
| 212 |
+
except Exception as e:
|
| 213 |
+
log.error("Emergency cloud vault restore failed: %s", e)
|
| 214 |
+
|
| 215 |
if current["status"] == "MISSING":
|
| 216 |
sqlite3.connect(RUNTIME_DB).close()
|
| 217 |
log.warning("No verified snapshot exists; initialized an empty runtime database")
|