Spaces:
Running
Running
File size: 2,951 Bytes
bdc2878 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | """Reverse pipeline feedback — translate ReverseResult into account + proxy feedback.
Called after every upstream call to update account health/quota and proxy state.
"""
from app.control.account.commands import AccountPatch
from app.control.proxy.models import ProxyFeedback, ProxyFeedbackKind
from app.platform.runtime.clock import now_ms
from .types import ResultCategory, ReverseResult
# ---------------------------------------------------------------------------
# Account feedback
# ---------------------------------------------------------------------------
def build_account_feedback(
token: str,
result: ReverseResult,
*,
mode_id: int = 0,
) -> AccountPatch:
"""Build an AccountPatch reflecting the outcome of a request.
SUCCESS → increment use_count, update last_use_at
RATE_LIMITED → decrement quota for the mode
AUTH_FAILURE → increment fail_count, set last_fail_reason
Others → increment fail_count
"""
ts = now_ms()
if result.category == ResultCategory.SUCCESS:
return AccountPatch(
token=token,
usage_use_delta=1,
last_use_at=ts,
)
if result.category == ResultCategory.RATE_LIMITED:
# Signal quota exhaustion for the specific mode.
quota_update: dict[str, dict] = {}
mode_key = {0: "quota_auto", 1: "quota_fast", 2: "quota_expert"}.get(mode_id)
if mode_key:
quota_update[mode_key] = {"remaining": 0}
return AccountPatch(
token=token,
usage_fail_delta=1,
last_fail_at=ts,
last_fail_reason=f"rate_limited (mode={mode_id})",
**({mode_key: quota_update[mode_key]} if mode_key and quota_update else {}),
)
return AccountPatch(
token=token,
usage_fail_delta=1,
last_fail_at=ts,
last_fail_reason=result.error or result.category.name,
)
# ---------------------------------------------------------------------------
# Proxy feedback
# ---------------------------------------------------------------------------
_CATEGORY_TO_PROXY: dict[ResultCategory, ProxyFeedbackKind] = {
ResultCategory.SUCCESS: ProxyFeedbackKind.SUCCESS,
ResultCategory.RATE_LIMITED: ProxyFeedbackKind.RATE_LIMITED,
ResultCategory.AUTH_FAILURE: ProxyFeedbackKind.UNAUTHORIZED,
ResultCategory.FORBIDDEN: ProxyFeedbackKind.CHALLENGE,
ResultCategory.UPSTREAM_5XX: ProxyFeedbackKind.UPSTREAM_5XX,
ResultCategory.TRANSPORT_ERR: ProxyFeedbackKind.TRANSPORT_ERROR,
}
def build_proxy_feedback(result: ReverseResult) -> ProxyFeedback:
"""Build a ProxyFeedback from a ReverseResult."""
kind = _CATEGORY_TO_PROXY.get(result.category, ProxyFeedbackKind.TRANSPORT_ERROR)
return ProxyFeedback(
kind=kind,
status_code=result.status_code,
reason=result.error,
)
__all__ = ["build_account_feedback", "build_proxy_feedback"]
|