NocoBase CronJobManager 定时任务管理注册、调度与生命周期全解析【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobaseCronJobManager是 NocoBase 服务端内置的定时任务管理器基于 cron实现。本指南面向 NocoBase 插件开发者讲解如何在插件中注册定时任务、理解CronJobParameters各参数的含义、编写 cron 表达式以及任务随应用启动/停止/重载的生命周期行为。读完本文你将能借助app.cronJobManager在自己的插件中实现“每日清理临时数据”“定时同步数据”“周期巡检”等典型能力。一、CronJobManager 是什么CronJobManager是 NocoBase 服务端在应用初始化阶段创建的定时任务管理器通过app.cronJobManager暴露给所有插件使用。其实现位于 packages/core/server/src/cron/cron-job-manager.ts内部直接封装了cron包的CronJob与CronJobParameters类型import { CronJob, CronJobParameters } from cron; import Application from ../application; export class CronJobManager { private _jobs: SetCronJob new Set(); private _started false; constructor(private app: Application) { app.on(beforeStop, async () { this.stop(); }); app.on(afterStart, async () { this.start(); }); app.on(beforeReload, async () { this.stop(); }); } public get started() { ... } public get jobs() { ... } public addJob(options: CronJobParameters) { ... } public removeJob(job: CronJob) { ... } public start() { ... } public stop() { ... } }从源码结构看CronJobManager的核心设计是面向集合的任务托管所有通过addJob()注册的CronJob被保存在SetCronJob集合中start()/stop()会遍历集合统一启停所有任务。应用在init()阶段创建该管理器见 packages/core/server/src/application.ts#L1268 的this._cronJobManager new CronJobManager(this);并通过get cronJobManager()访问器对外暴露packages/core/server/src/application.ts#L352-L355。二、基本用法在插件中注册一个定时任务定时任务的注册入口是this.app.cronJobManager.addJob()通常放在插件的load()或beforeLoad()生命周期中执行。文档给出的最小示例如下import { Plugin } from nocobase/server; export default class PluginCronDemo extends Plugin { async load() { this.app.cronJobManager.addJob({ cronTime: 0 0 * * *, // 每天 00:00 执行 onTick: async () { console.log(每日任务清理临时数据); await this.cleanTemporaryData(); }, timeZone: Asia/Shanghai, start: true, // 自动启动 }); } async cleanTemporaryData() { // 在此执行清理逻辑 } }对应地仓库中 packages/plugins/nocobase/plugin-ai/src/server/plugin.ts#L101-L113 就是一个真实的注册示例——AI 插件在beforeLoad()中注册了一个cronTime: 0 0 2 * * *每天凌晨 02:00的定时任务用于清理过期的 LangChain checkpoint 数据并且onTick内部用try/catch包裹并通过this.app.log.error()记录异常这是一个值得借鉴的健壮性写法this.app.cronJobManager.addJob({ cronTime: 0 0 2 * * *, onTick: async () { try { const checkpointSaver new SequelizeCollectionSaver(() this.app.mainDataSource); const checkpointCleaner new CheckpointCleaner(() this.app.mainDataSource, checkpointSaver); const expiredAt new Date(Date.now() - 48 * 60 * 60 * 1000); await checkpointCleaner.cleanOutdated(expiredAt); } catch (e) { this.app.log.error(langChain checkpoint clean job fail, e); } }, });三、CronJobParameters 参数说明CronJobParameters类型由cron包导出字段定义如下export declare interface CronJobParameters { cronTime: string | Date | DateTime; onTick: CronCommand; onComplete?: CronCommand | null; start?: boolean; timeZone?: string; context?: any; runOnInit?: boolean; utcOffset?: string | number; unrefTimeout?: boolean; }各参数含义与取值说明参数类型说明cronTimestring \| Date \| DateTime定时任务的时间表达式。支持标准 cron 表达式如0 0 * * *表示每天 00:00 执行也支持Date或 luxonDateTime对象后者可指定时区。onTickfunction任务主体函数在指定时间被触发执行。onCompletefunction当任务被job.stop()停止或onTick主动调用onComplete时执行适合做收尾清理。startboolean注册后是否立即启动任务。文档示例传入true自动启动也可以不传稍后通过job.start()手动启动。timeZonestring指定执行时区如Asia/Shanghai。设置后 cron 表达式将按该时区解释。contextany执行onTick时的上下文可在回调中通过this访问。runOnInitboolean是否在任务初始化时立即执行一次onTick。utcOffsetstring \| number指定 UTC 时区偏移量如08:00或480分钟与timeZone二选一使用。unrefTimeoutboolean是否对底层的 setTimeout 调用unref()即控制事件循环是否因该任务保持活跃。设为true时如果事件循环中没有其他任务进程可能退出适合不要求常驻的场景。需要说明的是cronTime同时支持Date类型一次性执行与DateTime类型可带时区的一次性执行若指定了timeZone则cronTime字符串中的第 5 个字段星期会被忽略因为时区下的星期由该时区的本地时间决定这在cron库的既有语义中如此设计。四、Cron 表达式示例CronJobManager使用标准的 5 段式 cron 表达式依次为分 时 日 月 星期常用示例表达式含义* * * * *每分钟执行一次0 * * * *每小时执行一次0 0 * * *每天 00:00 执行0 9 * * 1每周一 09:00 执行*/10 * * * *每 10 分钟执行一次提示cron包还支持带秒的 6 段式表达式如* * * * * *表示每秒仓库测试用例 packages/core/server/src/tests/cron.test.ts#L41-L54 中即使用* * * * * *验证每秒触发的行为两次onTick在 2 秒内被调用。生产任务建议使用分钟及以上粒度的表达式避免高频执行对数据库造成压力。需要精确调试表达式时可借助在线工具辅助生成与校验。五、控制任务的启动与停止addJob()会返回一个CronJob实例你可以用它来手动控制单个任务const job app.cronJobManager.addJob({ ... }); job.start(); // 启动任务 job.stop(); // 停止任务除单个任务的手动控制外CronJobManager还提供了集合级 APIcronJobManager.jobs获取当前托管的所有CronJob集合cronJobManager.start()统一启动集合内所有任务并将started置为truecronJobManager.stop()统一停止集合内所有任务并将started置为falsecronJobManager.removeJob(job)停止并从集合中移除指定任务。需要特别强调的是生命周期自动托管在 cron-job-manager.ts 的构造函数中CronJobManager监听应用事件并自动同步状态应用事件管理器的行为afterStart自动调用start()启动所有已注册任务beforeStop自动调用stop()停止所有任务beforeReload自动调用stop()停止所有任务重载后管理器会被重建因此定时任务会跟随应用启动和停止通常你不需要手动调用start()或stop()。只有当你需要临时暂停某个任务例如维护窗口期暂停数据同步时才需要显式操作返回的 job 对象。从源码结构还可以推断一个行为由于app.on(beforeReload)会触发stop()而应用重载app.reload()会重新执行init()并new CronJobManager(this)因此重载后app.cronJobManager会是一个全新的实例。这一点有测试用例直接印证——packages/core/server/src/tests/cron.test.ts#L29-L39 中应用reload()后旧实例cron1.started变为false且新旧实例cron1 ! cron2。这意味着插件中若在生命周期外持有旧的app.cronJobManager引用重载后可能失效应在需要时通过app.cronJobManager实时获取。六、测试验证与运行前提仓库为定时任务能力提供了完整的单元测试 packages/core/server/src/tests/cron.test.ts覆盖四条核心行为实例获取app.cronJobManager是CronJobManager的实例重载重建app.reload()后旧实例停止、新实例替换定时触发addJob注册* * * * * *任务并start()后2 秒内onTick被调用 2 次任务移除removeJob(job)后托管集合大小从 1 变为 0。这组测试同时给出了运行前提定时任务属于应用进程内的调度单进程内存调度依赖进程常驻。若需要在多实例部署集群模式下避免同一任务被多个实例重复执行应在业务层结合 NocoBase 的分布式锁lockManager等机制自行做幂等或互斥控制CronJobManager本身不提供跨实例的分布式调度保证。七、相关链接Plugin 插件 — 插件生命周期与核心 APIEvent 事件系统 — 应用事件的监听与触发服务端开发概述 — 服务端各模块一览插件开发概述 — 插件开发整体介绍CronJobManager 源码 — 任务管理器实现CronJobManager 单元测试 — 行为验证用例AI 插件真实使用示例 — 仓库内的落地实践【免费下载链接】nocobaseNocoBase is an open-source AI no-code platform for building business systems fast. Instead of generating everything from scratch, AI works on top of production-proven infrastructure and a WYSIWYG no-code interface, so you get both speed and reliability.项目地址: https://gitcode.com/GitHub_Trending/no/nocobase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
