"""多渠道网关异常基类。 插件在投递、校验或降级过程中应优先抛出这些异常,便于调度器区分 永久失败(应停止重试并标记死信)与可重试失败(应指数退避后重试)。 """ from enum import StrEnum class ChannelErrorClassification(StrEnum): """插件对投递异常的分类结果,供调度器决定重试策略。""" RETRYABLE = "retryable" # 网络抖动、服务端 5xx、未明确分类的瞬态故障 PERMANENT = "permanent" # 配置错误、凭证失效、用户被拉黑、内容永久拒绝 RATE_LIMITED = "rate_limited" # 明确限流,可配合 retry_after 退避 class ChannelError(Exception): """渠道网关相关异常的基类。""" class ChannelPermanentError(ChannelError): """渠道侧永久错误,不应重试。 例如:凭证失效、会话不存在、消息内容被渠道永久拒绝、用户已拉黑机器人等。 """ class ChannelValidationError(ChannelPermanentError): """入站/出站消息格式或签名校验失败。 属于永久失败,重复投递无法自动修复。 """ class ChannelRetryableError(ChannelError): """渠道侧可重试错误。 例如:网络超时、渠道服务端 5xx、限流(429)等瞬态故障。 """ class ChannelRateLimitedError(ChannelRetryableError): """渠道侧明确限流错误。 可配合 retry_after 进行退避;未提供时由调度器使用默认指数退避。 """ def __init__(self, *args: object, retry_after: int | None = None) -> None: super().__init__(*args) self.retry_after = retry_after class ChannelConfigurationError(ChannelPermanentError): """渠道配置缺失或非法导致的永久失败。""" class ChannelNotSupportedError(ChannelPermanentError): """当前渠道不支持某种消息类型或能力。""" class ChannelTransportReconnectRequested(ChannelError): """插件请求传输层立即断开并重连。 例如 Slack Socket Mode 收到 disconnect 信封后,需要主动断开当前连接 并让生命周期管理器重新建立连接。 """ class ChannelNotLoggedInError(ChannelError): """未登录时调用需要登录状态的操作(如发送消息)。"""