56 lines
2.0 KiB
Python
56 lines
2.0 KiB
Python
"""Durable delivery queue for alert notifications."""
|
|
|
|
import enum
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import BigInteger, Column, DateTime, Enum, Index, Integer, String, Text
|
|
|
|
from .device import Base
|
|
|
|
|
|
PRIMARY_KEY_TYPE = BigInteger().with_variant(Integer, "sqlite")
|
|
|
|
|
|
class NotificationStatus(str, enum.Enum):
|
|
"""Lifecycle states for a notification delivery attempt."""
|
|
|
|
pending = "pending"
|
|
sending = "sending"
|
|
sent = "sent"
|
|
failed = "failed"
|
|
|
|
|
|
class NotificationOutbox(Base):
|
|
"""A notification retained until a dispatcher records its final outcome."""
|
|
|
|
__tablename__ = "notification_outbox"
|
|
|
|
id = Column(PRIMARY_KEY_TYPE, primary_key=True, autoincrement=True)
|
|
alert_event_id = Column(BigInteger, nullable=False, index=True, comment="关联告警事件 ID")
|
|
message_content = Column(Text, nullable=False, comment="待发送的脱敏消息摘要")
|
|
delivery_scope = Column(String(256), nullable=True, comment="受控投递范围摘要")
|
|
status = Column(
|
|
Enum(NotificationStatus),
|
|
nullable=False,
|
|
default=NotificationStatus.pending,
|
|
server_default=NotificationStatus.pending.value,
|
|
comment="投递状态",
|
|
)
|
|
attempt_count = Column(Integer, nullable=False, default=0, comment="投递尝试次数")
|
|
next_attempt_at = Column(DateTime, nullable=True, comment="下次允许投递时间")
|
|
locked_at = Column(DateTime, nullable=True, comment="投递器领取时间")
|
|
sent_at = Column(DateTime, nullable=True, comment="成功投递时间")
|
|
last_error = Column(String(512), nullable=True, comment="最近一次投递错误摘要")
|
|
created_at = Column(DateTime, default=datetime.now, nullable=False, comment="创建时间")
|
|
updated_at = Column(
|
|
DateTime,
|
|
default=datetime.now,
|
|
onupdate=datetime.now,
|
|
nullable=False,
|
|
comment="更新时间",
|
|
)
|
|
|
|
__table_args__ = (
|
|
Index("idx_notification_outbox_status_next_attempt", "status", "next_attempt_at"),
|
|
)
|