自动排队生成量化因子挖掘任务,心跳派发后将高 IC 因子入库。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-10-11 01:49:16 +08:00
parent f0b35e6b34
commit 598cecad5f
11 changed files with 529 additions and 23 deletions
+16 -4
View File
@@ -24,6 +24,7 @@ from app.clock import utcnow
from app.config import settings
from app.errors import AppError
from app.models import ComputeNode, ComputeTask, NodeStatus, PushStatus, TaskStatus
from app.services.alpha_queue import ingest_alpha_factors
from app.services.common import get_node_by_sn
logger = logging.getLogger(__name__)
@@ -125,8 +126,15 @@ def dispatch_random_tasks(session: Session, now: datetime | None = None) -> list
"""向当前在线、授权仍有效、且没有未完成任务的节点随机下发一轮任务。"""
moment = now or utcnow()
expire_overdue_tasks(session, moment)
# 未绑定的挖掘切片不算占用节点。已派发的挖掘任务单独排队,不挡住模拟任务。
pending_node_ids = set(
session.scalars(select(ComputeTask.node_id).where(ComputeTask.status.in_(_BUSY))).all()
session.scalars(
select(ComputeTask.node_id).where(
ComputeTask.node_id.is_not(None),
ComputeTask.status.in_(_BUSY),
ComputeTask.task_type != "alpha_mining",
)
).all()
)
candidates = [
node
@@ -174,15 +182,16 @@ def list_pending_tasks(session: Session, sn: str, now: datetime | None = None) -
node = get_node_by_sn(session, sn.strip())
tasks = session.scalars(
select(ComputeTask)
.where(ComputeTask.node_id == node.id, ComputeTask.status == TaskStatus.PENDING)
.order_by(ComputeTask.dispatched_at)
.where(ComputeTask.node_id == node.id, ComputeTask.status.in_(_BUSY))
.order_by(ComputeTask.dispatched_at, ComputeTask.id)
).all()
visible: list[ComputeTask] = []
for task in tasks:
if task.deadline_at < moment:
task.status = TaskStatus.EXPIRED
continue
task.status = TaskStatus.PROCESSING
if task.status == TaskStatus.PENDING:
task.status = TaskStatus.PROCESSING
visible.append(task)
session.flush()
return visible
@@ -221,6 +230,8 @@ def report_task(
task.result = result or None
task.status = TaskStatus.COMPLETED if success else TaskStatus.FAILED
session.flush()
if task.status == TaskStatus.COMPLETED and task.task_type == "alpha_mining":
ingest_alpha_factors(session, task)
return task
@@ -228,6 +239,7 @@ def expire_overdue_tasks(session: Session, now: datetime | None = None) -> int:
moment = now or utcnow()
tasks = session.scalars(
select(ComputeTask).where(
ComputeTask.node_id.is_not(None),
ComputeTask.status.in_(_BUSY),
ComputeTask.deadline_at < moment,
)