You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
162 lines
4.5 KiB
162 lines
4.5 KiB
"""
|
|
定时任务接口 - 创建/启动/停止/删除/列表
|
|
"""
|
|
import logging
|
|
|
|
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.database import get_db
|
|
from app.schemas import (
|
|
CreateTaskRequest,
|
|
TaskInfo,
|
|
TaskListResponse,
|
|
)
|
|
from app.services.cache import (
|
|
create_task,
|
|
list_tasks,
|
|
get_task,
|
|
disable_task,
|
|
enable_task,
|
|
delete_task,
|
|
)
|
|
from app.services.scheduler import (
|
|
add_job,
|
|
remove_job,
|
|
is_job_running,
|
|
get_all_jobs,
|
|
)
|
|
|
|
logger = logging.getLogger(__name__)
|
|
router = APIRouter(prefix="/tasks", tags=["定时任务"])
|
|
|
|
|
|
@router.post("", response_model=TaskInfo)
|
|
def create_new_task(req: CreateTaskRequest, db: Session = Depends(get_db)):
|
|
"""
|
|
创建并启动一个定时采集任务。
|
|
输入品种合约和轮询时长,自动开始定时获取数据。
|
|
"""
|
|
task = create_task(
|
|
db=db,
|
|
symbol=req.symbol,
|
|
data_type=req.data_type,
|
|
periods=req.periods,
|
|
interval_seconds=req.interval_seconds,
|
|
)
|
|
|
|
# 注册到调度器
|
|
job_id = add_job(task.id, task.interval_seconds)
|
|
task.job_id = job_id
|
|
db.commit()
|
|
db.refresh(task)
|
|
|
|
return _to_task_info(task)
|
|
|
|
|
|
@router.get("", response_model=TaskListResponse)
|
|
def list_all_tasks(db: Session = Depends(get_db)):
|
|
"""列出所有定时任务"""
|
|
tasks = list_tasks(db)
|
|
job_status = get_all_jobs()
|
|
|
|
task_infos = []
|
|
for t in tasks:
|
|
running = is_job_running(t.id) if t.enabled else False
|
|
task_infos.append(TaskInfo(
|
|
id=t.id,
|
|
symbol=t.symbol,
|
|
data_type=t.data_type,
|
|
periods=t.periods.split(",") if t.periods else [],
|
|
interval_seconds=t.interval_seconds,
|
|
enabled=t.enabled,
|
|
running=running,
|
|
last_run=t.last_run.isoformat() if t.last_run else None,
|
|
last_status=t.last_status,
|
|
created_at=t.created_at.isoformat(),
|
|
updated_at=t.updated_at.isoformat(),
|
|
))
|
|
|
|
return TaskListResponse(tasks=task_infos, total=len(task_infos))
|
|
|
|
|
|
@router.post("/{task_id}/stop", response_model=TaskInfo)
|
|
def stop_task(task_id: int, db: Session = Depends(get_db)):
|
|
"""停止定时任务(从调度器移除,但保留配置)"""
|
|
task = get_task(db, task_id)
|
|
if not task:
|
|
raise HTTPException(status_code=404, detail=f"任务 {task_id} 不存在")
|
|
|
|
remove_job(task_id)
|
|
task = disable_task(db, task_id)
|
|
|
|
return _to_task_info(task)
|
|
|
|
|
|
@router.post("/{task_id}/start", response_model=TaskInfo)
|
|
def start_task(task_id: int, db: Session = Depends(get_db)):
|
|
"""重新启动已停止的定时任务"""
|
|
task = get_task(db, task_id)
|
|
if not task:
|
|
raise HTTPException(status_code=404, detail=f"任务 {task_id} 不存在")
|
|
|
|
enable_task(db, task_id)
|
|
add_job(task.id, task.interval_seconds)
|
|
db.refresh(task)
|
|
|
|
return _to_task_info(task)
|
|
|
|
|
|
@router.delete("/{task_id}")
|
|
def delete_existing_task(task_id: int, db: Session = Depends(get_db)):
|
|
"""删除定时任务(同时从调度器移除)"""
|
|
task = get_task(db, task_id)
|
|
if not task:
|
|
raise HTTPException(status_code=404, detail=f"任务 {task_id} 不存在")
|
|
|
|
remove_job(task_id)
|
|
delete_task(db, task_id)
|
|
|
|
return {"message": f"任务 {task_id} 已删除"}
|
|
|
|
|
|
@router.post("/{task_id}/update-interval", response_model=TaskInfo)
|
|
def update_interval(
|
|
task_id: int,
|
|
interval_seconds: int,
|
|
db: Session = Depends(get_db),
|
|
):
|
|
"""更新任务的轮询间隔"""
|
|
task = get_task(db, task_id)
|
|
if not task:
|
|
raise HTTPException(status_code=404, detail=f"任务 {task_id} 不存在")
|
|
|
|
task.interval_seconds = interval_seconds
|
|
task.updated_at = task.updated_at.__class__.now()
|
|
db.commit()
|
|
db.refresh(task)
|
|
|
|
# 如果任务正在运行,更新调度器
|
|
if task.enabled and is_job_running(task_id):
|
|
remove_job(task_id)
|
|
add_job(task.id, task.interval_seconds)
|
|
|
|
return _to_task_info(task)
|
|
|
|
|
|
def _to_task_info(task) -> TaskInfo:
|
|
"""ORM -> Pydantic"""
|
|
return TaskInfo(
|
|
id=task.id,
|
|
symbol=task.symbol,
|
|
data_type=task.data_type,
|
|
periods=task.periods.split(",") if task.periods else [],
|
|
interval_seconds=task.interval_seconds,
|
|
enabled=task.enabled,
|
|
running=is_job_running(task.id),
|
|
last_run=task.last_run.isoformat() if task.last_run else None,
|
|
last_status=task.last_status,
|
|
created_at=task.created_at.isoformat(),
|
|
updated_at=task.updated_at.isoformat(),
|
|
)
|