fix: reparent governance backend failures under GatewayUnavailableError (issue #7)
A fail-closed limiter or breaker backend means the scope cannot emit a single request, which is exactly scope-level unavailability. But the error sat directly under PolyGatewayError, so a caller writing only `except GatewayUnavailableError` dropped it into the catch-all branch: Redis blips once and a backlog of tasks burns its business failure budget into the dead letter queue, over a fault a restart would clear. Three gate paths leak to callers rather than being absorbed by _record_quietly (try_acquire, try_enter, progress_age_s); each is now pinned by a test, since none of them had one before. The two unknown-source sites move to SourceNotConfiguredError instead of following along. They report a misconfigured source name, not an outage, and letting them into the retryable family would be the mirror of the bug being fixed here: the task would retry forever and never surface.
This commit is contained in:
@@ -150,5 +150,29 @@ class SourceNotConfiguredError(PolyGatewayError):
|
||||
"""
|
||||
|
||||
|
||||
class GovernanceBackendError(PolyGatewayError):
|
||||
"""限流/熔断状态后端自身故障: 必须报错而非放行(防击穿网关,降级方向铁律)。"""
|
||||
class GovernanceBackendError(GatewayUnavailableError):
|
||||
"""限流/熔断状态后端自身故障: 必须报错而非放行(防击穿网关,降级方向铁律)。
|
||||
|
||||
继承 `GatewayUnavailableError`(issue #7): fail-closed 意味着整个 scope 一个
|
||||
请求都发不出去,语义上即 scope 级不可用。此前它是 `PolyGatewayError` 的直接
|
||||
子类,只写 `except GatewayUnavailableError` 的调用方接不住,后果是"Redis 抖
|
||||
一下 → 积压任务消耗业务失败预算 → 进死信",而那是运维重启即可恢复的故障。
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
message: str,
|
||||
*,
|
||||
scope: str,
|
||||
retry_after_s: float = GOVERNANCE_BACKEND_RETRY_AFTER_S,
|
||||
source_name: str | None = None,
|
||||
) -> None:
|
||||
super().__init__(
|
||||
scope=scope,
|
||||
reason="governance_backend_down",
|
||||
retry_after_s=retry_after_s,
|
||||
source_name=source_name,
|
||||
)
|
||||
# 父类会把 message 覆写为 "{scope} 网关暂时不可用: {reason}",而各构造点
|
||||
# 携带的诊断串(如"限流后端 try_acquire 失败: ...")是排障主线索,必须保住
|
||||
self.args = (message,)
|
||||
|
||||
Reference in New Issue
Block a user