修复图表多模型旧日期缓存

This commit is contained in:
2569718930@qq.com
2026-06-17 21:52:14 +08:00
parent 4b4fb92070
commit 566c47e683
2 changed files with 249 additions and 6 deletions
+135
View File
@@ -1311,6 +1311,141 @@ def test_chart_data_cache_hit_overlays_cached_multi_model_hourly(monkeypatch):
assert payload["multi_model"]["hourly_forecasts"]["ECMWF"] == [24.5]
def test_chart_data_cache_hit_replaces_stale_multi_model_hourly(monkeypatch):
import asyncio
class FakeCache:
def get_city_cache(self, kind, city):
assert kind == "full"
return {
"payload": {
"name": city,
"display_name": city.title(),
"local_date": "2026-06-17",
"local_time": "15:20",
"temp_symbol": "°C",
"current": {"temp": 20.0},
"hourly": {"times": ["15:00"], "temps": [20.0]},
"multi_model": {
"hourly_times": ["2026-06-14T15:00", "2026-06-16T23:00"],
"hourly_forecasts": {"ECMWF": [21.0, 22.0]},
},
},
}
def get_runway_obs_recent(self, icao, minutes=60):
return []
class DummyLock:
def __enter__(self):
return None
def __exit__(self, *_args):
return False
collector = city_api.legacy_routes._weather
monkeypatch.setattr(collector, "multi_model_cache_version", "v5")
monkeypatch.setattr(collector, "_open_meteo_cache", {})
monkeypatch.setattr(collector, "_multi_model_cache", {
"48.9694:2.4414:paris:c:v5": {
"data": {
"hourly_times": ["2026-06-17T15:00", "2026-06-17T16:00"],
"hourly_forecasts": {"ECMWF": [24.5, 25.0]},
"forecasts": {"ECMWF": 27.0},
}
}
})
monkeypatch.setattr(collector, "_open_meteo_cache_lock", DummyLock())
monkeypatch.setattr(collector, "_multi_model_cache_lock", DummyLock())
monkeypatch.setattr(collector, "_maybe_reload_open_meteo_disk_cache", lambda: None)
monkeypatch.setattr(city_api.legacy_routes, "_CACHE_DB", FakeCache())
monkeypatch.setattr(city_api.legacy_routes, "_city_cache_is_fresh", lambda entry, ttl: True)
monkeypatch.setattr(
city_api.legacy_routes,
"_overlay_latest_wunderground_current",
lambda city, payload: payload,
)
payload = asyncio.run(city_api._get_city_chart_data("paris", force_refresh=False))
assert payload["multi_model"]["hourly_times"] == ["2026-06-17T15:00", "2026-06-17T16:00"]
assert payload["multi_model"]["hourly_forecasts"]["ECMWF"] == [24.5, 25.0]
def test_chart_data_cache_hit_refreshes_when_multi_model_cache_is_stale(monkeypatch):
import asyncio
class FakeCache:
def get_city_cache(self, kind, city):
assert kind == "full"
return {
"payload": {
"name": city,
"display_name": city.title(),
"local_date": "2026-06-17",
"local_time": "15:20",
"temp_symbol": "°C",
"current": {"temp": 20.0},
"hourly": {"times": ["15:00"], "temps": [20.0]},
"multi_model": {
"hourly_times": ["2026-06-14T15:00", "2026-06-16T23:00"],
"hourly_forecasts": {"ECMWF": [21.0, 22.0]},
},
},
}
def get_runway_obs_recent(self, icao, minutes=60):
return []
class DummyLock:
def __enter__(self):
return None
def __exit__(self, *_args):
return False
collector = city_api.legacy_routes._weather
fetch_calls = []
monkeypatch.setattr(collector, "multi_model_cache_version", "v5")
monkeypatch.setattr(collector, "_open_meteo_cache", {})
monkeypatch.setattr(collector, "_multi_model_cache", {
"48.9694:2.4414:paris:c:v5": {
"t": 1781695200,
"data": {
"hourly_times": ["2026-06-14T15:00", "2026-06-16T23:00"],
"hourly_forecasts": {"ECMWF": [21.0, 22.0]},
"forecasts": {"ECMWF": 22.0},
},
}
})
monkeypatch.setattr(collector, "_open_meteo_cache_lock", DummyLock())
monkeypatch.setattr(collector, "_multi_model_cache_lock", DummyLock())
monkeypatch.setattr(collector, "_maybe_reload_open_meteo_disk_cache", lambda: None)
monkeypatch.setattr(
collector,
"fetch_multi_model",
lambda lat, lon, city, use_fahrenheit: fetch_calls.append((lat, lon, city, use_fahrenheit))
or {
"hourly_times": ["2026-06-17T15:00", "2026-06-17T16:00"],
"hourly_forecasts": {"ECMWF": [24.5, 25.0]},
"forecasts": {"ECMWF": 27.0},
},
)
monkeypatch.setattr(city_api.legacy_routes, "_CACHE_DB", FakeCache())
monkeypatch.setattr(city_api.legacy_routes, "_city_cache_is_fresh", lambda entry, ttl: True)
monkeypatch.setattr(
city_api.legacy_routes,
"_overlay_latest_wunderground_current",
lambda city, payload: payload,
)
payload = asyncio.run(city_api._get_city_chart_data("paris", force_refresh=False))
assert fetch_calls == [(48.9694, 2.4414, "paris", False)]
assert payload["multi_model"]["hourly_times"] == ["2026-06-17T15:00", "2026-06-17T16:00"]
assert payload["multi_model"]["hourly_forecasts"]["ECMWF"] == [24.5, 25.0]
def test_chart_data_cache_hit_overlays_latest_amsc_raw(monkeypatch):
import asyncio