Commit verified recovery projections atomically

This commit is contained in:
2026-08-03 06:09:52 +02:00
parent 842be5edb5
commit 79d00b84e3
3 changed files with 78 additions and 6 deletions
+35 -6
View File
@@ -113,12 +113,35 @@ class DurableRecoveryOperation:
) -> None:
"""Commit domain writes and verified success in one DB transaction."""
self._commit_atomic_terminal(
self._commit_terminal(
session,
status=RecoveryStatus.SUCCEEDED,
summary="Operation effects and authoritative state were verified",
kind="verified-success",
evidence=evidence,
require_atomic_mode=True,
)
def commit_verified_success(
self,
session: Session,
*,
evidence: dict[str, Any],
) -> None:
"""Commit a verified success projection and checkpoint together.
Non-atomic operations use this only after their external effect has a
conclusive provider result. It does not make that effect atomic; it
prevents local success from outrunning its durable verification.
"""
self._commit_terminal(
session,
status=RecoveryStatus.SUCCEEDED,
summary="Operation effects and authoritative state were verified",
kind="verified-success",
evidence=evidence,
require_atomic_mode=False,
)
def commit_atomic_failure(
@@ -130,12 +153,13 @@ class DurableRecoveryOperation:
) -> None:
"""Commit domain failure evidence and the terminal state atomically."""
self._commit_atomic_terminal(
self._commit_terminal(
session,
status=RecoveryStatus.FAILED,
summary=summary,
kind="verified-failure",
evidence=evidence,
require_atomic_mode=True,
)
def commit_atomic_rejection(
@@ -147,12 +171,13 @@ class DurableRecoveryOperation:
) -> None:
"""Commit a definitive rejection and its domain evidence atomically."""
self._commit_atomic_terminal(
self._commit_terminal(
session,
status=RecoveryStatus.REJECTED,
summary=summary,
kind="verified-rejection",
evidence=evidence,
require_atomic_mode=True,
)
def fail(self, *, summary: str, evidence: dict[str, Any]) -> None:
@@ -375,7 +400,7 @@ class DurableRecoveryOperation:
self.lease_claim = claim
return operation, claim
def _commit_atomic_terminal(
def _commit_terminal(
self,
session: Session,
*,
@@ -383,16 +408,20 @@ class DurableRecoveryOperation:
summary: str,
kind: str,
evidence: dict[str, Any],
require_atomic_mode: bool,
) -> None:
if status not in {
RecoveryStatus.SUCCEEDED,
RecoveryStatus.FAILED,
RecoveryStatus.REJECTED,
}:
raise ValueError("Unsupported atomic terminal recovery status")
raise ValueError("Unsupported terminal recovery status")
try:
operation, claim = self._locked_and_renewed(session)
if operation.mode != RecoveryMode.ATOMIC.value:
if (
require_atomic_mode
and operation.mode != RecoveryMode.ATOMIC.value
):
raise RecoveryGuaranteeError(
"Atomic terminal commits require an atomic recovery plan"
)