fix: 热点穿透盘中缓存过期改为同步重建,避免显示上个交易日旧图

fetch_theme_graph 原用 stale-while-revalidate:缓存过期先返回旧数据、
后台异步重建。缓存里若是上个交易日数据,过期后用户一直看到旧图,
重建完成前不会更新。

- 交易时段缓存过期/无缓存 → 同步重建(加锁去重),绝不返回旧数据
- 非交易时段过期 → 保留 stale-while-revalidate(行情无实时变化,秒开无害)

实测盘中同步重建约 7s,可接受。

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Sakurasan
2026-08-10 13:47:21 +08:00
co-authored by Claude
parent 1550291d6b
commit ce131b2867
+14 -12
View File
@@ -399,10 +399,11 @@ async def _rebuild_task(cache_key: str, sort_field: int, top_n: int, lock: async
async def fetch_theme_graph(sort_field: int = 1, top_n: int = 30, limit: int = 1000) -> dict:
"""获取热点穿透图数据(盘中 60s 缓存 + stale-while-revalidate
"""获取热点穿透图数据(盘中 60s 缓存,盘中过期同步重建,非盘中 stale-while-revalidate
缓存命中且未过期 → 直接返回;已过期 → 返回旧数据并后台异步重建(秒开);
无缓存 → 同步构建(并发下加锁去重)。返回前按 limit 裁剪 stocks。
缓存新鲜 → 直接返回;
非交易时段过期 → 返回旧数据并后台异步重建(秒开,非盘中行情无实时变化,旧值可接受);
交易时段过期 / 无缓存 → 同步重建(加锁去重),绝不返回上个交易日的旧图。
Args:
sort_field: 题材排序 1=涨幅, 4=热度
@@ -412,20 +413,21 @@ async def fetch_theme_graph(sort_field: int = 1, top_n: int = 30, limit: int = 1
cache_key = f"theme_graph:{sort_field}:{top_n}"
data, expires_at = _get_graph_cache(cache_key)
if data is not None:
# 缓存新鲜直接返回;过期返回旧数据并后台刷新
if not (expires_at and expires_at > time.time()):
_spawn_rebuild(cache_key, sort_field, top_n)
if data is not None and expires_at and expires_at > time.time():
# 缓存新鲜直接返回
return _trim_graph_result(data, limit)
# 无缓存:同步构建(并发下加锁去重)
# 非交易时段过期:行情无实时变化,先返回旧值(秒开),后台异步重建
if data is not None and not _is_trading_time():
_spawn_rebuild(cache_key, sort_field, top_n)
return _trim_graph_result(data, limit)
# 交易时段过期 / 无缓存:同步重建,加锁去重
lock = _REBUILD_LOCKS.setdefault(cache_key, asyncio.Lock())
async with lock:
data, expires_at = _get_graph_cache(cache_key)
if data is not None:
# 等待锁期间已被其他请求写入
if not (expires_at and expires_at > time.time()):
_spawn_rebuild(cache_key, sort_field, top_n)
if data is not None and expires_at and expires_at > time.time():
# 等待锁期间已被其他请求刷新
return _trim_graph_result(data, limit)
data = await _build_theme_graph(sort_field, top_n)
_set_graph_cache(cache_key, data)