mirror of
https://ghfast.top/https://github.com/aeroxw/tick-stock-panel.git
synced 2026-09-12 15:34:16 +08:00
feat(realtime): 首用门禁 — 本地无数据时禁止开启实时行情
日K/enriched 均空 (与看板首用弹窗同口径) 时开启实时行情返回 409 并给 同步指引, 不落偏好。展示/监控/梯队全部依赖本地数据底座, 空数据下轮询 只是空转耗配额且缺 instruments 维表。只拦开启不影响关闭, 已开后清库 下次重开自然被拦。
This commit is contained in:
@@ -932,6 +932,16 @@ def update_realtime_quotes(req: RealtimeQuotesPrefs, request: Request) -> dict:
|
||||
qs.disable()
|
||||
_sync_depth_polling(False)
|
||||
return {"realtime_quotes_enabled": False, "realtime_allowed": False}
|
||||
if req.realtime_quotes_enabled:
|
||||
# 首用门禁: 本地完全无数据 (日K/enriched 均空, 与看板首用弹窗同口径) 时
|
||||
# 禁止开启 — 实时行情的展示 (enriched 底座 + 快照覆盖)、监控、连板梯队
|
||||
# 全部依赖本地数据, 空数据下轮询只是空转耗配额, 且无 instruments 维表。
|
||||
repo = getattr(request.app.state, "repo", None)
|
||||
if repo is not None and repo.latest_daily_date() is None and repo.latest_enriched_date() is None:
|
||||
raise HTTPException(
|
||||
status_code=409,
|
||||
detail="本地暂无行情数据,请先在「数据」页同步后再开启实时行情",
|
||||
)
|
||||
if req.realtime_quotes_enabled and qs and qs.is_paused():
|
||||
# 管道/数据修正运行期间禁止开启实时行情 — 防止写盘竞态
|
||||
raise HTTPException(status_code=409, detail="数据同步运行中,实时行情已临时暂停,请稍后再开启")
|
||||
|
||||
@@ -227,14 +227,19 @@ def test_describe_and_issue_dataclass():
|
||||
# ── 开实时行情门禁 (钩子2) ──────────────────────────────────────────
|
||||
|
||||
|
||||
def _gate_state(tmp_path, quote_service, repo):
|
||||
def _gate_state(tmp_path, quote_service, repo, *, has_data=True):
|
||||
from types import SimpleNamespace
|
||||
|
||||
return SimpleNamespace(
|
||||
app=SimpleNamespace(state=SimpleNamespace(
|
||||
quote_service=quote_service,
|
||||
depth_service=None,
|
||||
repo=SimpleNamespace(store=SimpleNamespace(data_dir=tmp_path)),
|
||||
repo=SimpleNamespace(
|
||||
store=SimpleNamespace(data_dir=tmp_path),
|
||||
# 首用门禁判据: 日K/enriched 最近日期 (None = 本地无数据)
|
||||
latest_daily_date=lambda: date(2026, 8, 28) if has_data else None,
|
||||
latest_enriched_date=lambda: None,
|
||||
),
|
||||
capabilities=None,
|
||||
))
|
||||
)
|
||||
@@ -298,6 +303,30 @@ def test_realtime_gate_blocks_on_snapshot_and_launches_repair(tmp_path, monkeypa
|
||||
assert saved == {}
|
||||
|
||||
|
||||
def test_realtime_gate_blocks_when_no_local_data(tmp_path, monkeypatch):
|
||||
"""首用门禁: 日K/enriched 均无数据时禁止开启实时行情 (409 + 同步指引),
|
||||
且不落偏好 (开关不生效)。"""
|
||||
from fastapi import HTTPException
|
||||
|
||||
from app.api import settings as settings_api
|
||||
|
||||
saved = {}
|
||||
monkeypatch.setattr(
|
||||
"app.services.preferences.save", lambda payload: saved.update(payload),
|
||||
)
|
||||
|
||||
qs = _QuoteServiceStub()
|
||||
request = _gate_state(tmp_path, qs, repo=None, has_data=False)
|
||||
req = settings_api.RealtimeQuotesPrefs(realtime_quotes_enabled=True)
|
||||
|
||||
with pytest.raises(HTTPException) as exc_info:
|
||||
settings_api.update_realtime_quotes(req, request)
|
||||
|
||||
assert exc_info.value.status_code == 409
|
||||
assert "同步" in exc_info.value.detail
|
||||
assert saved == {} # 未开启
|
||||
|
||||
|
||||
def test_realtime_gate_allows_clean_data(tmp_path, monkeypatch):
|
||||
from app.api import settings as settings_api
|
||||
|
||||
|
||||
Reference in New Issue
Block a user