72 lines
2.2 KiB
Python
72 lines
2.2 KiB
Python
"""多渠道网关异常基类。
|
||
|
||
插件在投递、校验或降级过程中应优先抛出这些异常,便于调度器区分
|
||
永久失败(应停止重试并标记死信)与可重试失败(应指数退避后重试)。
|
||
"""
|
||
|
||
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):
|
||
"""未登录时调用需要登录状态的操作(如发送消息)。"""
|