扫描终端优化:增加并发到6、超时60s、启动预热全城缓存
MAX_WORKERS 2→6,BUILD_TIMEOUT 22→60s。新增 start_scan_terminal_prewarm:服务启动时后台跑全城 _analyze(),后续扫描直接命中缓存。app_factory 在路由注册后触发热身。
This commit is contained in:
@@ -16,6 +16,7 @@ from web.routers.payments import router as payments_router
|
||||
from web.routers.scan import router as scan_router
|
||||
from web.routers.system import router as system_router
|
||||
from web.routes import router as legacy_router
|
||||
from web.scan_terminal_service import start_scan_terminal_prewarm
|
||||
|
||||
_ROUTES_REGISTERED_FLAG = "_polyweather_routes_registered"
|
||||
|
||||
@@ -32,4 +33,5 @@ def create_app() -> FastAPI:
|
||||
core_app.include_router(ops_router)
|
||||
core_app.include_router(legacy_router)
|
||||
setattr(core_app.state, _ROUTES_REGISTERED_FLAG, True)
|
||||
start_scan_terminal_prewarm()
|
||||
return core_app
|
||||
|
||||
@@ -1544,3 +1544,58 @@ def build_scan_terminal_ai_payload(
|
||||
reason=str(exc),
|
||||
duration_ms=duration_ms,
|
||||
)
|
||||
|
||||
|
||||
_SCAN_PREWARM_STARTED = False
|
||||
_SCAN_PREWARM_LOCK = threading.Lock()
|
||||
|
||||
|
||||
def start_scan_terminal_prewarm() -> None:
|
||||
"""Warm analysis caches for all cities at startup so the first terminal
|
||||
scan returns quickly instead of forcing every city through a cold
|
||||
_analyze() path.
|
||||
|
||||
Runs once per process. Safe to call from any thread and at any point
|
||||
during the server lifecycle.
|
||||
"""
|
||||
global _SCAN_PREWARM_STARTED
|
||||
with _SCAN_PREWARM_LOCK:
|
||||
if _SCAN_PREWARM_STARTED:
|
||||
return
|
||||
_SCAN_PREWARM_STARTED = True
|
||||
|
||||
city_names = list(CITIES.keys())
|
||||
logger.info(
|
||||
"scan terminal pre-warm starting cities={} workers={}",
|
||||
len(city_names),
|
||||
SCAN_TERMINAL_MAX_WORKERS,
|
||||
)
|
||||
|
||||
def _warm_one(city: str) -> str:
|
||||
try:
|
||||
_analyze(city, force_refresh=False, detail_mode="panel")
|
||||
except Exception:
|
||||
pass
|
||||
return city
|
||||
|
||||
def _run():
|
||||
started = time.time()
|
||||
ok = 0
|
||||
workers = max(1, min(SCAN_TERMINAL_MAX_WORKERS, len(city_names)))
|
||||
with ThreadPoolExecutor(max_workers=workers) as ex:
|
||||
futures = {ex.submit(_warm_one, c): c for c in city_names}
|
||||
for f in as_completed(futures):
|
||||
try:
|
||||
f.result()
|
||||
ok += 1
|
||||
except Exception:
|
||||
pass
|
||||
elapsed = int(time.time() - started)
|
||||
logger.info(
|
||||
"scan terminal pre-warm finished ok={}/{} elapsed={}s",
|
||||
ok,
|
||||
len(city_names),
|
||||
elapsed,
|
||||
)
|
||||
|
||||
threading.Thread(target=_run, name="scan-prewarm", daemon=True).start()
|
||||
|
||||
Reference in New Issue
Block a user