Add at-least-once delivery + idempotent federation handler
- EventProcessor now recovers stuck "processing" activities back to "pending" after 5 minutes (handles process crashes) - New ap_delivery_log table records successful inbox deliveries - Federation delivery handler checks the log before sending, so retries skip already-delivered inboxes - Together these give at-least-once + idempotent semantics Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -427,3 +427,27 @@ class APNotification(Base):
|
||||
Index("ix_ap_notification_read", "actor_profile_id", "read"),
|
||||
Index("ix_ap_notification_created", "created_at"),
|
||||
)
|
||||
|
||||
|
||||
class APDeliveryLog(Base):
|
||||
"""Tracks successful deliveries of activities to remote inboxes.
|
||||
|
||||
Used for idempotency: the delivery handler skips inboxes that already
|
||||
have a success row, so retries after a crash never send duplicates.
|
||||
"""
|
||||
__tablename__ = "ap_delivery_log"
|
||||
|
||||
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
|
||||
activity_id: Mapped[int] = mapped_column(
|
||||
Integer, ForeignKey("ap_activities.id", ondelete="CASCADE"), nullable=False,
|
||||
)
|
||||
inbox_url: Mapped[str] = mapped_column(String(512), nullable=False)
|
||||
status_code: Mapped[int | None] = mapped_column(Integer, nullable=True)
|
||||
delivered_at: Mapped[datetime] = mapped_column(
|
||||
DateTime(timezone=True), nullable=False, server_default=func.now(),
|
||||
)
|
||||
|
||||
__table_args__ = (
|
||||
UniqueConstraint("activity_id", "inbox_url", name="uq_delivery_activity_inbox"),
|
||||
Index("ix_ap_delivery_activity", "activity_id"),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user