refactor: govern background job execution
This commit is contained in:
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user