| """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 |
|
|
|
|
| |
| |
| |
|
|
| 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: |
| |
| 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, |
| ) |
|
|
|
|
| |
| |
| |
|
|
| _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"] |
|
|