fix: keep the accounting path degrading after the wrapper change

Letting SourceNotConfiguredError through the gate wrappers opened a hole
the recheck caught: _record_quietly only degrades GovernanceBackendError,
so an assembly defect raised from the accounting side would now escape and
destroy a response from a call that had already genuinely succeeded. That
inverts the exact invariant _record_quietly exists to hold.

Widening _record_quietly is the right fix rather than narrowing the
wrappers, because that layer degrades by what the path is (accounting, the
call is already done) rather than by which error type shows up. Narrowing
would have left 4 of 9 wrapper methods as exceptions to a rule nobody can
remember.

No backend raises it from an accounting method today, so this is a
guardrail for whoever adds source-name validation to a breaker backend.

The stub that first reported this green was wrong: its record_success
lacked count_attempt, so it raised TypeError and the wrapper relabeled it.
Fixed signature, then the test failed as it should have.

Also finishes the three-to-five leak path correction across the four
remaining spots, including the wiki summary card that indexes this design.
This commit is contained in:
2026-08-06 06:39:52 -04:00
parent a57a5cea72
commit 5853c3f8ff
8 changed files with 45 additions and 8 deletions
+2 -1
View File
@@ -28,6 +28,7 @@ from polygateway.errors import (
RequestRejectedError,
ResultInvalidError,
SourceDeadError,
SourceNotConfiguredError,
TransientError,
)
from polygateway.middleware.breaker import BreakerGate
@@ -401,7 +402,7 @@ class RetryMW:
await write_back
except asyncio.CancelledError:
raise
except GovernanceBackendError as exc:
except (GovernanceBackendError, SourceNotConfiguredError) as exc:
logger.warning("治理记账写回降级(不冒泡): {}", exc)
def _feed_outcome(self, source_name: str, ok: bool) -> None: