"""Named durable-operation crash injection used by recovery qualification."""

from __future__ import annotations

from dataclasses import dataclass
from typing import Final, Protocol, final, override


@final
class CrashFaultError(RuntimeError):
    """Injected process interruption at one named durable checkpoint."""

    __slots__ = ("checkpoint",)

    def __init__(self, checkpoint: str) -> None:
        super().__init__(checkpoint)
        self.checkpoint = checkpoint

    @override
    def __str__(self) -> str:
        return f"injected crash at {self.checkpoint}"


class FaultInjector(Protocol):
    """A deterministic named checkpoint sink."""

    def hit(self, checkpoint: str) -> None: ...


@dataclass(frozen=True, slots=True)
class NoFaults:
    """Production checkpoint sink that never interrupts."""

    def hit(self, checkpoint: str) -> None:
        """Accept a checkpoint without interruption."""
        del checkpoint


@dataclass(frozen=True, slots=True)
class CrashAt:
    """Interrupt exactly when a selected checkpoint is reached."""

    target: str

    def hit(self, checkpoint: str) -> None:
        """Raise at the selected durable operation."""
        if checkpoint == self.target:
            raise CrashFaultError(checkpoint)


NO_FAULTS: Final = NoFaults()
