feat: add SourceNotConfiguredError and the governance backend reason
Pure addition ahead of the reparenting, so this commit leaves every existing caller and test untouched. SourceNotConfiguredError deliberately stays outside GatewayUnavailableError: a source name that is not in the limiter's config dict is an assembly defect, not a transient outage, and folding it into the retryable family would let a typo retry forever without ever reaching a dead letter queue. The retry_after_s default is 5.0 rather than 0 because a backlog released at zero delay would stampede a backend that is already down.
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
import pytest
|
||||
|
||||
from polygateway.errors import (
|
||||
GOVERNANCE_BACKEND_RETRY_AFTER_S,
|
||||
SCOPE_REASONS,
|
||||
AllSourcesExhausted,
|
||||
CircuitOpenError,
|
||||
GatewayUnavailableError,
|
||||
@@ -11,6 +13,7 @@ from polygateway.errors import (
|
||||
RequestRejectedError,
|
||||
ResultInvalidError,
|
||||
SourceDeadError,
|
||||
SourceNotConfiguredError,
|
||||
TransientError,
|
||||
)
|
||||
|
||||
@@ -89,3 +92,36 @@ class TestBackendFailure:
|
||||
exc = GovernanceBackendError("redis down")
|
||||
assert isinstance(exc, PolyGatewayError)
|
||||
assert not isinstance(exc, TransientError)
|
||||
|
||||
|
||||
class TestSourceNotConfigured:
|
||||
"""装配缺陷有意留在 scope 级家族之外(issue #7 §3.4,Q1 人类拍板)。"""
|
||||
|
||||
def test_is_domain_error_but_not_scope_level(self):
|
||||
exc = SourceNotConfiguredError("未知源 'nope'(scope=llm)")
|
||||
assert isinstance(exc, PolyGatewayError)
|
||||
# 关键断言: 归入可重投家族会让配置写错的任务永远重投、永不进死信
|
||||
assert not isinstance(exc, GatewayUnavailableError)
|
||||
|
||||
def test_exported_at_package_top_level(self):
|
||||
import polygateway
|
||||
|
||||
assert polygateway.SourceNotConfiguredError is SourceNotConfiguredError
|
||||
assert "SourceNotConfiguredError" in polygateway.__all__
|
||||
|
||||
|
||||
class TestGovernanceBackendReason:
|
||||
"""新 scope 级 reason 值域(issue #7 §3.1)。"""
|
||||
|
||||
def test_reason_admitted_to_scope_domain(self):
|
||||
assert "governance_backend_down" in SCOPE_REASONS
|
||||
|
||||
def test_gateway_unavailable_accepts_the_new_reason(self):
|
||||
exc = AllSourcesExhausted(
|
||||
scope="LLM", reason="governance_backend_down", retry_after_s=0.0
|
||||
)
|
||||
assert exc.reason == "governance_backend_down"
|
||||
|
||||
def test_retry_after_default_is_non_zero(self):
|
||||
"""取 0 会让积压任务零延迟冲击已挂掉的后端(§3.2)。"""
|
||||
assert GOVERNANCE_BACKEND_RETRY_AFTER_S > 0
|
||||
|
||||
Reference in New Issue
Block a user