checkpoint: 调度任务存储落 PG——jobstore 归一 default + execute 写回真实触发 + 前端 store 字典更新

- ap_scheduler: 默认分组改 SQLAlchemyJobStore on PG,删 RedisJobStore 与 redis_instance;注释/告警口径同步
- node/service: jobstore 归一 default(兼容存量 sqlalchemy 名);cron/interval/date 写回 task_node.trigger/trigger_args(前端列表可见真实触发);run_job_now 用独立临时 id,不再覆盖节点既有排程
- enums: 删 APSCHEDULER_LOCK_KEY(jobstore 落 PG 后死锁)
- sys_dict_data: sys_job_store 字典归一 default,删 sqlalchemy 档
- 前端: 任务表单 store 选项与 default 归一
This commit is contained in:
34047007@qq.com
2026-08-07 21:47:38 +08:00
parent 86126ea16f
commit 73e25050df
6 changed files with 61 additions and 46 deletions
+5 -16
View File
@@ -18,13 +18,11 @@ from apscheduler.executors.asyncio import AsyncIOExecutor
from apscheduler.executors.pool import ProcessPoolExecutor, ThreadPoolExecutor
from apscheduler.job import Job
from apscheduler.jobstores.memory import MemoryJobStore
from apscheduler.jobstores.redis import RedisJobStore
from apscheduler.jobstores.sqlalchemy import SQLAlchemyJobStore
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
from apscheduler.triggers.date import DateTrigger
from apscheduler.triggers.interval import IntervalTrigger
from redis.asyncio import Redis
from sqlalchemy.orm import Session
from app.config.setting import settings
@@ -37,15 +35,9 @@ JOB_STATUS_FAILED = 3
scheduler = AsyncIOScheduler()
scheduler.configure(
jobstores={
"default": RedisJobStore(
host=settings.REDIS_HOST,
port=int(settings.REDIS_PORT),
username=settings.REDIS_USER or None,
password=settings.REDIS_PASSWORD or None,
db=int(settings.REDIS_DB_NAME),
protocol=2,
),
"sqlalchemy": SQLAlchemyJobStore(url=settings.DB_URI, engine=engine),
# 默认分组 = PostgreSQLapscheduler_jobs 表):任务持久化,随 pg_data 每日备份;
# 与业务主库同生共死,不再依赖可降级/无备份的 Redis(多 Worker 场景本系统不适用,见运营手册)
"default": SQLAlchemyJobStore(url=settings.DB_URI, engine=engine),
"memory": MemoryJobStore(),
},
executors={
@@ -64,7 +56,6 @@ scheduler.configure(
class SchedulerUtil:
"""定时任务 SDK — 仅封装 APScheduler 核心操作,不含业务逻辑(无 ORM/实体引用)。"""
redis_instance: Redis | None = None
job_name_cache: dict[str, str | tuple[str, str]] = {}
@classmethod
@@ -129,15 +120,13 @@ class SchedulerUtil:
logger.info("所有任务已从调度器中移除")
@classmethod
async def init_scheduler(cls, redis: Redis | None = None) -> None:
async def init_scheduler(cls) -> None:
"""应用启动时初始化定时任务调度器(含系统级周期任务注册)。
返回:
- None
"""
try:
if redis:
cls.redis_instance = redis
scheduler.start()
scheduler.add_listener(cls._dispatch_job_event, EVENT_ALL)
scheduler.resume()
@@ -177,7 +166,7 @@ class SchedulerUtil:
@classmethod
def shutdown(cls, wait: bool = False) -> None:
# Redis 不可达时 start()/add_job 可能失败导致调度器未真正运行:
# jobstore 已落 PG:数据库不可达时 start()/add_job 可能失败导致调度器未真正运行:
# 对未运行实例调用 shutdown 会抛 SchedulerNotRunningError,须先判状态
if not scheduler.running:
return