Source code for alchemiq.outbox.publisher

"""Publisher protocol and error hierarchy for outbox delivery adapters."""

from __future__ import annotations

from typing import TYPE_CHECKING, Protocol, runtime_checkable

if TYPE_CHECKING:
    from alchemiq.outbox.message import OutboxMessage  # ty: ignore[unresolved-import]


[docs] class PublishError(Exception): """Base exception for publisher delivery errors."""
[docs] class TransientPublishError(PublishError): """Broker unreachable or connection lost. When raised by a :class:`.Publisher`, the :class:`.Relay` rolls back the whole batch without incrementing ``attempts`` and sleeps ``error_backoff`` seconds before retrying. Use this for temporary infrastructure failures, not logical errors. """
[docs] @runtime_checkable class Publisher(Protocol): """Structural protocol for outbox delivery adapters. Implementations must expose ``publish(message)``. An optional ``publish_batch(messages)`` method is detected by duck-typing when present; it is **not** part of this protocol contract, so any object with just ``publish`` satisfies ``isinstance(obj, Publisher)``. E.g.:: from alchemiq.outbox import Publisher, TransientPublishError from alchemiq.outbox.message import OutboxMessage class MyBrokerPublisher: async def publish(self, message: OutboxMessage) -> None: try: await broker.send(message.topic, message.payload) except BrokerConnectionError as e: raise TransientPublishError(str(e)) from e .. seealso:: :class:`.Relay` - background loop that calls this protocol. """
[docs] async def publish(self, message: OutboxMessage) -> None: """Deliver a single message to the broker. Raise :class:`.TransientPublishError` for connection failures; the relay backs off without incrementing ``attempts``. Raise any other exception to poison the row (increment ``attempts``; mark ``failed`` or ``dead``). :param message: the outbox row projected to a broker-agnostic value object. :raises TransientPublishError: for transient broker connection failures. """ ...
# publish_batch is an OPTIONAL capability detected by duck-typing (hasattr). # It is NOT part of the Protocol contract, so any object with just `publish` # satisfies isinstance(obj, Publisher).