fix(overview): dashboard top indices now sync with realtime quotes (#84)

看板顶部四个指数在开启实时行情时不刷新, 但左侧菜单的指数能刷新。

根因: build_market_overview 在装配前会把 as_of 从 None 解析为真实日期
(latest_date), 导致 _index_quotes 内 `as_of is None` 判断永远为 False,
实时缓存分支走不到, 始终回退 kline_index_daily 数据库快照。

- market_overview_builder: 仅当调用方显式指定日期(历史复盘)时才让
  _index_quotes 回退数据库; "最新"请求传 None 优先读实时缓存
  (_index_quotes 自身有实时为空回退数据库的兜底, 盘后不受影响)
- quote_service: 实时刷新后清空 overview 聚合缓存, 使 SSE 触发的重取
  拿到最新值, 与侧栏 /intraday/indices (无缓存) 行为对齐
This commit is contained in:
wshy
2026-07-09 13:49:41 +08:00
committed by GitHub
parent be2215725e
commit fff7f73a9f
2 changed files with 11 additions and 1 deletions
@@ -367,9 +367,12 @@ def build_market_overview(
as_of: 指定日期,None 则取最新有数据日。
"""
svc = ScreenerService(repo)
# 调用方未指定日期时视为"最新"请求: 指数行情走实时缓存 (quote_service),
# 其余装配仍以解析出的真实日期为准。显式指定日期(历史复盘)时才回退数据库。
explicit_as_of = as_of is not None
as_of = as_of or svc.latest_date()
status = _quote_status(quote_service)
indices = _index_quotes(repo, quote_service, as_of)
indices = _index_quotes(repo, quote_service, None if not explicit_as_of else as_of)
if not as_of:
return {
+7
View File
@@ -310,6 +310,13 @@ class QuoteService:
return list(self._subscribers)
def _broadcast_quote_updated(self) -> None:
# 实时行情刷新后清空总览聚合缓存, 使看板 (overview-market) 在 SSE 触发的
# 重取中拿到最新指数/聚合值。与 _broadcast 同时进行, 与侧栏 /intraday/indices
# (无缓存, 直读实时缓存) 行为对齐, 避免看板落后于侧栏。
# 延迟导入规避 services <-> api 层循环依赖。
from app.api.overview import invalidate_overview_cache
invalidate_overview_cache()
for sub in self._snapshot_subscribers():
sub.notify_quote()