fix: quarantine failed product cleanups in failed_cleanup state
This commit is contained in:
@@ -318,7 +318,9 @@ class ProductArchiveStore:
|
||||
raise ValueError(f"unknown version_id for product: {version_id}")
|
||||
|
||||
def mark_pending_cleanup(self, product_id: str, now: datetime) -> ProductRecord:
|
||||
self.get_product(product_id)
|
||||
product = self.get_product(product_id)
|
||||
if product.status not in ("active", "failed_cleanup"):
|
||||
raise ValueError("product cannot be marked pending cleanup")
|
||||
purge_after = now + timedelta(days=30)
|
||||
self._execute(
|
||||
"UPDATE products SET status = ?, purge_after = ?, updated_at = ? WHERE product_id = ?",
|
||||
@@ -355,8 +357,8 @@ class ProductArchiveStore:
|
||||
)
|
||||
conn.execute(
|
||||
"""UPDATE cleanup_records SET status = ?, completed_at = ?
|
||||
WHERE product_id = ? AND status = ?""",
|
||||
("restored", restored_at.isoformat(), product_id, "pending_cleanup"),
|
||||
WHERE product_id = ? AND status IN ('pending_cleanup', 'failed_cleanup')""",
|
||||
("restored", restored_at.isoformat(), product_id),
|
||||
)
|
||||
return self.get_product(product_id)
|
||||
|
||||
@@ -405,13 +407,29 @@ class ProductArchiveStore:
|
||||
return None
|
||||
return self._product_from_row(row)
|
||||
|
||||
def release_product_purge(self, product_id: str) -> None:
|
||||
"""Return a failed physical deletion claim to its pending state."""
|
||||
self._execute(
|
||||
"""UPDATE cleanup_records SET status = 'pending_cleanup'
|
||||
WHERE product_id = ? AND status = 'purging'""",
|
||||
(product_id,),
|
||||
)
|
||||
def fail_product_purge(self, product_id: str) -> ProductRecord:
|
||||
"""Quarantine a purge whose physical deletion failed mid-way."""
|
||||
with self._lock, self._connect() as conn:
|
||||
conn.execute("BEGIN IMMEDIATE")
|
||||
claim = conn.execute(
|
||||
"""SELECT 1 FROM cleanup_records
|
||||
WHERE product_id = ? AND status = 'purging' LIMIT 1""",
|
||||
(product_id,),
|
||||
).fetchone()
|
||||
if claim is None:
|
||||
raise ValueError("product purge is not claimed")
|
||||
updated = conn.execute(
|
||||
"""UPDATE cleanup_records SET status = 'failed_cleanup'
|
||||
WHERE product_id = ? AND status = 'purging'""",
|
||||
(product_id,),
|
||||
)
|
||||
if updated.rowcount != 1:
|
||||
raise ValueError("product purge is not claimed")
|
||||
conn.execute(
|
||||
"UPDATE products SET status = 'failed_cleanup', updated_at = ? WHERE product_id = ?",
|
||||
(_now().isoformat(), product_id),
|
||||
)
|
||||
return self.get_product(product_id)
|
||||
|
||||
def finalize_product_purge(self, product_id: str, now: datetime) -> ProductRecord:
|
||||
"""Atomically mark a claimed product purged after file removal."""
|
||||
|
||||
Reference in New Issue
Block a user