fix(sidecar-v2): second-round review fixes
- cooldown_manager: move function-level imports to module top - proxy.py: emergency_count counter now actually increments - server.py: metrics reads emergency_count from proxy module - dashboard.html: real JS CDN fallback (not just comment) - requirements.txt: remove unused prometheus_client Round 2 review residual fixes from 沈路明/陆怀瑾/梁思筑 feedback Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -4,7 +4,7 @@ import time
|
|||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
import structlog
|
import structlog
|
||||||
from config import config
|
from config import config
|
||||||
from storage.backend_store import set_backend_cooldown, clear_backend_cooldown
|
from storage.backend_store import set_backend_cooldown, clear_backend_cooldown, get_backend
|
||||||
from storage.cooldown_store import log_cooldown_event, end_cooldown_event
|
from storage.cooldown_store import log_cooldown_event, end_cooldown_event
|
||||||
|
|
||||||
logger = structlog.get_logger("sidecar_v2.cooldown_manager")
|
logger = structlog.get_logger("sidecar_v2.cooldown_manager")
|
||||||
@@ -57,7 +57,6 @@ def check_and_clear_cooldown(backend_id: str) -> bool:
|
|||||||
|
|
||||||
Returns True if cooldown was cleared (backend is back online).
|
Returns True if cooldown was cleared (backend is back online).
|
||||||
"""
|
"""
|
||||||
from storage.backend_store import get_backend
|
|
||||||
backend = get_backend(backend_id, decrypt_key=False)
|
backend = get_backend(backend_id, decrypt_key=False)
|
||||||
if backend is None:
|
if backend is None:
|
||||||
return False
|
return False
|
||||||
@@ -97,7 +96,6 @@ def precheck_cooldown(backend_id: str) -> bool:
|
|||||||
If cooldown will expire within config.cooldown_precheck_threshold_seconds,
|
If cooldown will expire within config.cooldown_precheck_threshold_seconds,
|
||||||
skip the backend so we don't hit it again right as it expires.
|
skip the backend so we don't hit it again right as it expires.
|
||||||
"""
|
"""
|
||||||
from storage.backend_store import get_backend
|
|
||||||
backend = get_backend(backend_id, decrypt_key=False)
|
backend = get_backend(backend_id, decrypt_key=False)
|
||||||
if backend is None or backend.status != "cooling":
|
if backend is None or backend.status != "cooling":
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -4,9 +4,25 @@
|
|||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Sidecar V2 — Provider Pool Dashboard</title>
|
<title>Sidecar V2 — Provider Pool Dashboard</title>
|
||||||
|
<!-- Primary: jsDelivr CDN -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
|
||||||
<!-- CDN fallback: place chart.umd.min.js in static/ for offline deployments -->
|
<!-- Fallback: local static copy for offline/intranet deployments -->
|
||||||
<script>if(typeof Chart==='undefined'){document.write('<script src="/static/chart.umd.min.js"><\/script>')}</script>
|
<script>
|
||||||
|
(function() {
|
||||||
|
var check = function() {
|
||||||
|
if (typeof Chart === 'undefined') {
|
||||||
|
var s = document.createElement('script');
|
||||||
|
s.src = '/static/chart.umd.min.js';
|
||||||
|
s.onerror = function() {
|
||||||
|
console.warn('Chart.js unavailable (CDN + local both failed). Charts disabled.');
|
||||||
|
};
|
||||||
|
document.head.appendChild(s);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Check after CDN script has had a chance to load
|
||||||
|
setTimeout(check, 2000);
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
--bg: #0f1117;
|
--bg: #0f1117;
|
||||||
|
|||||||
@@ -18,6 +18,14 @@ from cooldown_manager import start_cooldown, check_and_clear_cooldown
|
|||||||
from storage.models import Backend
|
from storage.models import Backend
|
||||||
from storage.usage_store import record_usage
|
from storage.usage_store import record_usage
|
||||||
|
|
||||||
|
# Emergency activation counter (read by metrics endpoint)
|
||||||
|
_emergency_count: int = 0
|
||||||
|
|
||||||
|
|
||||||
|
def get_emergency_count() -> int:
|
||||||
|
return _emergency_count
|
||||||
|
|
||||||
|
|
||||||
logger: structlog.stdlib.BoundLogger = structlog.get_logger("sidecar_v2.proxy")
|
logger: structlog.stdlib.BoundLogger = structlog.get_logger("sidecar_v2.proxy")
|
||||||
|
|
||||||
|
|
||||||
@@ -299,6 +307,9 @@ async def handle_proxy_request(
|
|||||||
emergency_rpm=emergency_rpm,
|
emergency_rpm=emergency_rpm,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Track emergency activation for metrics
|
||||||
|
_emergency_count += 1
|
||||||
|
|
||||||
# Emergency: try to get a token from any fallback backend at reduced RPM
|
# Emergency: try to get a token from any fallback backend at reduced RPM
|
||||||
emergency_retries = 3
|
emergency_retries = 3
|
||||||
for attempt in range(emergency_retries):
|
for attempt in range(emergency_retries):
|
||||||
|
|||||||
@@ -4,4 +4,3 @@ uvicorn[standard]>=0.30.0,<1.0.0
|
|||||||
httpx>=0.27.0,<1.0.0
|
httpx>=0.27.0,<1.0.0
|
||||||
structlog>=24.0.0,<25.0.0
|
structlog>=24.0.0,<25.0.0
|
||||||
cryptography>=42.0.0,<44.0.0
|
cryptography>=42.0.0,<44.0.0
|
||||||
prometheus_client>=0.20.0,<1.0.0
|
|
||||||
@@ -19,7 +19,7 @@ from crypto import init_crypto, is_initialized
|
|||||||
from pool_manager import PoolManager
|
from pool_manager import PoolManager
|
||||||
from rate_limiter import PerBackendRateLimiter
|
from rate_limiter import PerBackendRateLimiter
|
||||||
from router import Router
|
from router import Router
|
||||||
from proxy import handle_proxy_request
|
from proxy import handle_proxy_request, get_emergency_count
|
||||||
|
|
||||||
from storage.db import init_db, create_tables, run_integrity_check, get_connection, _DB_PATH
|
from storage.db import init_db, create_tables, run_integrity_check, get_connection, _DB_PATH
|
||||||
from storage.backend_store import (
|
from storage.backend_store import (
|
||||||
@@ -378,9 +378,8 @@ async def metrics() -> Response:
|
|||||||
cooling_count = sum(1 for b in all_backends if b.status == "cooling")
|
cooling_count = sum(1 for b in all_backends if b.status == "cooling")
|
||||||
lines.append(f"sidecar_cooldown_active {cooling_count}")
|
lines.append(f"sidecar_cooldown_active {cooling_count}")
|
||||||
|
|
||||||
# Emergency count
|
# Emergency count (from proxy module)
|
||||||
emergency_count = _metrics_counters.get("emergency_count", 0)
|
lines.append(f"sidecar_emergency_count {get_emergency_count()}")
|
||||||
lines.append(f"sidecar_emergency_count {emergency_count}")
|
|
||||||
|
|
||||||
# DB sizes
|
# DB sizes
|
||||||
from storage.db import get_db_sizes
|
from storage.db import get_db_sizes
|
||||||
|
|||||||
Reference in New Issue
Block a user