机场推送重构:观测缓存分离 + 全城市覆盖 + 四路并发

- 新增 force_refresh_observations_only 模式:机场推送仅刷新 METAR/AMOS
  观测缓存,多模型预报缓存保留 15 分钟,杜绝 Open-Meteo 429 限流后
  DEB 回退到实测温度的 bug
- 砍掉夜间静默和温度状态机,每条新观测无条件推送
- HIGH_FREQ_AIRPORT_CITIES 从 19 城扩到 30 城(新增 11 个美国城市)
- 美国城市走 airport_primary (MADIS) 优先取温
- 机场周期从串行改为 ThreadPoolExecutor(max_workers=4),周期时间从
  ~120s 压缩到 ~33s

Constraint: 单核 VPS 安全并发上限
Tested: docker compose up -d --build polyweather 重建后推送正常
This commit is contained in:
2569718930@qq.com
2026-05-17 18:04:05 +08:00
parent 58e6557c66
commit d39534dff4
3 changed files with 242 additions and 208 deletions
+12 -4
View File
@@ -1656,11 +1656,18 @@ def _archive_intraday_path_snapshot(city: str, result: Dict[str, Any]) -> None:
def _analyze(
city: str,
force_refresh: bool = False,
force_refresh_observations_only: bool = False,
include_llm_commentary: bool = False,
detail_mode: str = "full",
) -> Dict[str, Any]:
"""Fetch, analyse, and return structured weather data for one city."""
# Check cache
"""Fetch, analyse, and return structured weather data for one city.
Set *force_refresh_observations_only* to True for high-frequency
observation loops that need fresh METAR/AMOS/runway data but should
keep the longer-lived multi-model forecast caches intact so the DEB
blending does not fall back to the current observed temperature.
"""
# Check cache skip when explicitly refreshing observations
ttl = _analysis_ttl_for_city(city)
normalized_detail_mode_raw = str(detail_mode or "full").strip().lower()
if normalized_detail_mode_raw == "panel":
@@ -1672,8 +1679,8 @@ def _analyze(
else:
normalized_detail_mode = "full"
cache_key = _analysis_cache_key(city, normalized_detail_mode)
if not force_refresh:
if not force_refresh and not force_refresh_observations_only:
cached = _cache.get(cache_key)
if cached and _time.time() - cached["t"] < ttl:
if include_llm_commentary:
@@ -1707,6 +1714,7 @@ def _analyze(
lat=lat,
lon=lon,
force_refresh=force_refresh,
force_refresh_observations_only=force_refresh_observations_only,
include_taf=not is_panel_mode and not is_nearby_mode and not is_market_mode,
include_nearby=not is_panel_mode and not is_market_mode,
include_ensemble=not is_panel_mode and not is_nearby_mode and not is_market_mode,