refactor: govern background job execution

This commit is contained in:
leefer
2026-07-29 19:57:31 +08:00
parent 02af8488b3
commit 5f0b9735bd
15 changed files with 520 additions and 52 deletions
+41 -45
View File
@@ -192,14 +192,15 @@ class DashboardService:
self.mentor_skills = self.container.mentor_skills
self.realtime_aggregator = self.container.realtime_aggregator
self.chart_data = self.container.chart_data
self.jobs = self.container.jobs
self.screener.ensure_builtin_strategies()
self._background_stop = threading.Event()
self._background_thread = threading.Thread(
target=self._background_refresh_loop,
name="market-background-refresh",
daemon=True,
self._background_thread = self.jobs.start_scheduler(
self._background_refresh_tick,
self._background_stop,
interval_seconds=5,
initial_delay_seconds=3,
)
self._background_thread.start()
def _tushare_client(self) -> TushareClient:
gateway = getattr(self, "data_gateway", None)
@@ -583,6 +584,7 @@ class DashboardService:
self._system_credentials.get("background_refresh_enabled", True)
),
**self.database.status(),
"jobs": self.jobs.repository.recent(12),
},
"llm": {
"primary_configured": self._profile_configured(platform["primary"]),
@@ -772,36 +774,32 @@ class DashboardService:
raise ValueError("用户不存在。")
def request_background_sync(self, trade_date: str) -> bool:
if self.sync_lock.locked():
return False
normalized = normalize_date(trade_date)
threading.Thread(
target=self._run_background_sync,
args=(normalized,),
name=f"market-sync-{normalized}",
daemon=True,
).start()
return True
key = f"manual:{normalized}:{time.time_ns()}"
return self.jobs.submit(
"market.refresh",
key,
lambda: self.sync_dashboard(normalized),
{"trade_date": normalized, "trigger": "administrator"},
)
def _run_background_sync(self, trade_date: str) -> None:
try:
self.sync_dashboard(trade_date)
except Exception:
def _background_refresh_tick(self) -> None:
if not (
self.configured
and self._system_credentials.get("background_refresh_enabled", True)
):
return
def _background_refresh_loop(self) -> None:
self._background_stop.wait(3)
while not self._background_stop.is_set():
try:
if self.configured and self._system_credentials.get("background_refresh_enabled", True):
today = date.today().strftime("%Y%m%d")
snapshot = self.database.get_snapshot(today) or {}
if self._realtime_snapshot_due(today, snapshot):
self._run_background_sync(today)
self._schedule_automatic_screeners(today, snapshot)
except Exception:
pass
self._background_stop.wait(5)
today = date.today().strftime("%Y%m%d")
snapshot = self.database.get_snapshot(today) or {}
if self._realtime_snapshot_due(today, snapshot):
bucket = int(time.time() // 5)
self.jobs.submit(
"market.refresh",
f"realtime:{today}:{bucket}",
lambda: self.sync_dashboard(today),
{"trade_date": today, "trigger": "realtime-poll"},
)
self._schedule_automatic_screeners(today, snapshot)
def register_account(self, username: str, password: str) -> dict[str, Any]:
username = username.strip()
@@ -1743,13 +1741,12 @@ class DashboardService:
if last_attempt and (now - last_attempt).total_seconds() < 600:
return False
self._auto_screener_last_attempt[normalized_date] = now
threading.Thread(
target=self.run_automatic_screeners,
args=(normalized_date,),
name=f"automatic-screeners-{normalized_date}",
daemon=True,
).start()
return True
return self.jobs.submit(
"screener.automatic",
f"{normalized_date}:v{SCREENER_LIBRARY_VERSION}",
lambda: self.run_automatic_screeners(normalized_date),
{"trade_date": normalized_date, "trigger": "post-close"},
)
def run_automatic_screeners(self, trade_date: str) -> dict[str, Any]:
normalized_date = normalize_date(trade_date)
@@ -4586,13 +4583,12 @@ class DashboardService:
now = datetime.now().astimezone()
if trade_date == now.strftime("%Y%m%d") and now.time().replace(tzinfo=None) < dt_time(15, 0):
return
thread = threading.Thread(
target=self._refresh_ifind_event_enrichment,
args=(trade_date,),
name=f"ifind-event-{trade_date}",
daemon=True,
self.jobs.submit(
"market.ifind-event-enrichment",
f"{trade_date}:v1",
lambda: self._refresh_ifind_event_enrichment(trade_date),
{"trade_date": trade_date, "trigger": "dashboard-enrichment"},
)
thread.start()
def _refresh_ifind_event_enrichment(self, trade_date: str) -> None:
if not self._ifind_event_lock.acquire(blocking=False):