微信小程序页面迁移校验之前 P5任务处理之前

This commit is contained in:
Neo
2026-03-09 01:19:21 +08:00
parent 263bf96035
commit 6e20987d2f
1112 changed files with 153824 additions and 219694 deletions

View File

@@ -1,12 +1,14 @@
# -*- coding: utf-8 -*-
"""调度任务 CRUD API
提供 5 个端点:
提供 8 个端点:
- GET /api/schedules — 列表(按 site_id 过滤)
- POST /api/schedules — 创建
- POST /api/schedules — 创建(支持 run_immediately
- PUT /api/schedules/{id} — 更新
- DELETE /api/schedules/{id} — 删除
- PATCH /api/schedules/{id}/toggle — 启用/禁用
- GET /api/schedules/{id}/history — 调度任务执行历史
- POST /api/schedules/{id}/run — 手动执行一次(不更新调度间隔)
所有端点需要 JWT 认证site_id 从 JWT 提取。
"""
@@ -17,7 +19,7 @@ import json
import logging
from datetime import datetime, timezone
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi import APIRouter, Depends, HTTPException, Query, status
from app.auth.dependencies import CurrentUser, get_current_user
from app.database import get_connection
@@ -26,7 +28,10 @@ from app.schemas.schedules import (
ScheduleResponse,
UpdateScheduleRequest,
)
from app.schemas.execution import ExecutionHistoryItem
from app.schemas.tasks import TaskConfigSchema
from app.services.scheduler import calculate_next_run
from app.services.task_queue import task_queue
logger = logging.getLogger(__name__)
@@ -92,7 +97,7 @@ async def create_schedule(
body: CreateScheduleRequest,
user: CurrentUser = Depends(get_current_user),
) -> ScheduleResponse:
"""创建调度任务,自动计算 next_run_at。"""
"""创建调度任务,自动计算 next_run_at。支持 run_immediately 立即入队执行一次。"""
now = datetime.now(timezone.utc)
next_run = calculate_next_run(body.schedule_config, now)
@@ -124,7 +129,18 @@ async def create_schedule(
finally:
conn.close()
return _row_to_response(row)
response = _row_to_response(row)
# 立即执行一次(入队,不影响调度间隔)
if body.run_immediately:
try:
config = TaskConfigSchema(**body.task_config)
config = config.model_copy(update={"store_id": user.site_id})
task_queue.enqueue(config, user.site_id, schedule_id=response.id)
except Exception:
logger.warning("创建调度后立即执行入队失败 schedule_id=%s", response.id, exc_info=True)
return response
# ── PUT /api/schedules/{id} — 更新 ──────────────────────────
@@ -291,3 +307,88 @@ async def toggle_schedule(
conn.close()
return _row_to_response(updated_row)
# ── POST /api/schedules/{id}/run — 手动执行一次 ──────────────
@router.post("/{schedule_id}/run")
async def run_schedule_now(
schedule_id: str,
user: CurrentUser = Depends(get_current_user),
) -> dict:
"""手动触发调度任务执行一次,不更新 last_run_at / next_run_at / run_count。
读取调度任务的 task_config构造 TaskConfigSchema 后入队执行。
"""
conn = get_connection()
try:
with conn.cursor() as cur:
cur.execute(
"SELECT task_config, site_id FROM scheduled_tasks WHERE id = %s AND site_id = %s",
(schedule_id, user.site_id),
)
row = cur.fetchone()
conn.commit()
finally:
conn.close()
if row is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="调度任务不存在",
)
task_config_raw = row[0] if isinstance(row[0], dict) else json.loads(row[0])
config = TaskConfigSchema(**task_config_raw)
config = config.model_copy(update={"store_id": user.site_id})
task_id = task_queue.enqueue(config, user.site_id, schedule_id=schedule_id)
return {"message": "已提交到执行队列", "task_id": task_id}
# ── GET /api/schedules/{id}/history — 执行历史 ────────────────
@router.get("/{schedule_id}/history", response_model=list[ExecutionHistoryItem])
async def get_schedule_history(
schedule_id: str,
page: int = Query(1, ge=1),
page_size: int = Query(50, ge=1, le=200),
user: CurrentUser = Depends(get_current_user),
) -> list[ExecutionHistoryItem]:
"""获取调度任务的执行历史记录,按开始时间倒序,支持分页。"""
offset = (page - 1) * page_size
conn = get_connection()
try:
with conn.cursor() as cur:
cur.execute(
"""
SELECT id, site_id, task_codes, status, started_at, finished_at,
exit_code, duration_ms, command, summary, schedule_id
FROM task_execution_log
WHERE schedule_id = %s AND site_id = %s
ORDER BY started_at DESC
LIMIT %s OFFSET %s
""",
(schedule_id, user.site_id, page_size, offset),
)
rows = cur.fetchall()
conn.commit()
finally:
conn.close()
return [
ExecutionHistoryItem(
id=str(row[0]),
site_id=row[1],
task_codes=row[2] or [],
status=row[3],
started_at=row[4],
finished_at=row[5],
exit_code=row[6],
duration_ms=row[7],
command=row[8],
summary=row[9],
schedule_id=str(row[10]) if row[10] else None,
)
for row in rows
]