feat(edifabric): surface retry_after_seconds on quota-blocked responses
EdifabricError now carries an optional retry_after_seconds kwarg parsed from the upstream Retry-After header (API Management quota policy always sends this on 429/403 quota responses). The spot-check driver threads the value into each transport_error entry of spot-check.json so the operator sees the exact moment quota replenishes rather than parsing it out of the response body. Adds a MockTransport test confirming retry_after_seconds is set when the upstream sends Retry-After. Existing callers are unaffected (retry_after_seconds defaults to None and is keyword-only).
This commit is contained in:
@@ -136,6 +136,28 @@ def test_validate_interchange_raises_on_5xx():
|
||||
assert "upstream overloaded" in str(exc_info.value.body)
|
||||
|
||||
|
||||
def test_read_interchange_raises_with_retry_after_when_quota_blocked():
|
||||
"""On HTTP 403 with a ``Retry-After`` header (API Management quota
|
||||
policy), the raised EdifabricError exposes ``retry_after_seconds``
|
||||
so callers can sleep exactly until quota replenishes."""
|
||||
|
||||
def handler(request: httpx.Request) -> httpx.Response:
|
||||
return httpx.Response(
|
||||
403,
|
||||
headers={"Retry-After": "50492"},
|
||||
json={"statusCode": 403,
|
||||
"message": "Out of call volume quota."},
|
||||
)
|
||||
|
||||
_install_factory(handler)
|
||||
with pytest.raises(edifabric.EdifabricError) as exc_info:
|
||||
edifabric.read_interchange(b"ISA*...", api_key=_TEST_KEY)
|
||||
err = exc_info.value
|
||||
assert err.status_code == 403
|
||||
assert err.retry_after_seconds == 50492
|
||||
assert "Out of call volume quota" in str(err.body)
|
||||
|
||||
|
||||
# --- validate_edi (composed) ------------------------------------------
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user