Coverage for src / lexigram / contracts / notification / delivery.py: 100%
18 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-19 05:41 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-19 05:41 +0800
1"""DeliveryStoreProtocol — contract for persistent notification delivery tracking."""
3from __future__ import annotations
5from enum import StrEnum
6from typing import Any, Protocol, runtime_checkable
9class DeliveryStatus(StrEnum):
10 """States in the delivery lifecycle."""
12 PENDING = "pending"
13 DELIVERED = "delivered"
14 RETRYING = "retrying"
15 FAILED = "failed"
18@runtime_checkable
19class DeliveryStoreProtocol(Protocol):
20 """Protocol for persisting notification delivery attempts.
22 Implementations record each send attempt and its outcome so that
23 delivery history is preserved for auditing, alerting, and dead-letter
24 inspection. A single delivery operation may generate multiple attempt
25 records when retry logic is in play.
26 """
28 async def record_attempt(
29 self,
30 delivery_id: str,
31 recipient: str,
32 subject: str,
33 attempt_number: int,
34 ) -> None:
35 """Record a delivery attempt.
37 Args:
38 delivery_id: Stable identifier for the overall delivery operation.
39 recipient: Comma-separated list of recipient addresses.
40 subject: Message subject line.
41 attempt_number: 1-based attempt counter within this delivery.
42 """
43 ...
45 async def create_pending(self, message: Any) -> str:
46 """Record a new pending delivery and return its delivery_id.
48 Args:
49 message: The message being sent.
51 Returns:
52 A unique delivery_id string for tracking this delivery.
53 """
54 ...
56 async def mark_delivered(self, delivery_id: str) -> None:
57 """Mark a delivery as successfully delivered.
59 Args:
60 delivery_id: Identifier for the delivery operation.
61 """
62 ...
64 async def get_retry_count(self, delivery_id: str) -> int:
65 """Return the number of delivery attempts made so far.
67 Args:
68 delivery_id: Identifier for the delivery operation.
70 Returns:
71 Current attempt count.
72 """
73 ...
75 async def increment_retry(self, delivery_id: str) -> int:
76 """Increment the attempt counter and return the new value.
78 Args:
79 delivery_id: Identifier for the delivery operation.
81 Returns:
82 New attempt count after incrementing.
83 """
84 ...
86 async def schedule_retry(self, delivery_id: str, delay_seconds: float) -> None:
87 """Schedule a retry after ``delay_seconds``.
89 Args:
90 delivery_id: Identifier for the delivery operation.
91 delay_seconds: Seconds to wait before retrying.
92 """
93 ...
95 async def mark_failed(
96 self,
97 delivery_id: str,
98 reason: str = "",
99 final: bool = True,
100 ) -> None:
101 """Mark a delivery attempt as failed.
103 Args:
104 delivery_id: Identifier for the delivery operation.
105 reason: Human-readable failure description.
106 final: ``True`` when all retry attempts are exhausted and no further
107 sends will be attempted. ``False`` for intermediate failures
108 where retry is still pending.
109 """
110 ...
113__all__ = ["DeliveryStatus", "DeliveryStoreProtocol"]