"""In-process idempotent event delivery for the v3 delivery boundary.""" from __future__ import annotations from copy import deepcopy from typing import Any class IdempotentInProcessPublisher: """A small delivery adapter with durable-outbox compatible semantics. The process-local sink is intentionally only a delivery mechanism: SQLite remains the durable event source. The event ID is retained so a later durable broker/websocket adapter can make the same idempotency guarantee. """ def __init__(self) -> None: self._seen_event_ids: set[int] = set() self.delivered: list[dict[str, Any]] = [] async def publish(self, event: dict[str, Any]) -> None: event_id = event.get("event_id") if not isinstance(event_id, int): raise ValueError("Published outbox event has no integer event_id") if event_id in self._seen_event_ids: return self._seen_event_ids.add(event_id) self.delivered.append(deepcopy(event))