@core 基础设施
@skyroc/scheduler
协作式任务调度中枢,统一管理初始化 / 周期 / 监听三类任务
概览
| 项 | 值 |
|---|---|
| 包名 | @skyroc/scheduler |
| 版本 | 1.0.0 |
| 依赖 | 无(零运行时依赖) |
| 测试 | ✅ 1 个 task-hub.test.ts |
@skyroc/scheduler 提供一个单一心跳(setInterval)的协作式调度器,把分散的初始化逻辑、周期任务、事件监听全部收拢到一处管理。它解决「应用启动期 N 个 useEffect、N 个 setInterval、N 个监听器」造成的难以治理的副作用泥潭。
三类任务
| 类型 | 触发时机 | 典型场景 |
|---|---|---|
init | 启动时执行一次,支持依赖 + 优先级 | 拉取用户信息、初始化主题、加载菜单 |
periodic | 按 interval 周期执行 | 心跳、token 续期、轮询通知 |
listener | 启动时 run() 注册监听,关闭时 cleanup() 释放 | window 事件、订阅推送 |
核心特性
| 特性 | 说明 |
|---|---|
| 单心跳 | 全局一个 setInterval(tickInterval) 检查所有任务,避免散落的定时器 |
| 依赖图 | deps: string[] 声明前置任务,DAG 拓扑保证顺序 |
| 优先级 | 同层任务按 priority 排序 |
| 指数退避 | 失败自动重试,baseRetryDelay * 2^attempt,超过 maxRetries 标记 failed |
| 级联阻塞 | 依赖失败的下游任务标记 blocked,不再尝试 |
onReady 回调 | 所有 init 完成时触发,方便启动后续流程 |
默认参数
| 常量 | 值 |
|---|---|
tickInterval | 1000ms |
maxRetries | 3 |
baseRetryDelay | 1000ms(指数退避基线) |
periodic 默认 interval | 5000ms |
类型导出
type TaskType = 'init' | 'periodic' | 'listener';
type TaskStatus = 'pending' | 'running' | 'done' | 'failed' | 'blocked';
interface TaskDef {
name: string;
type: TaskType;
run: () => void | Promise<void>;
deps?: string[];
priority?: number;
interval?: number; // periodic 专用
cleanup?: () => void; // listener 专用
}
interface TaskHubOptions {
tickInterval?: number;
maxRetries?: number;
onReady?: () => void;
onTaskError?: (name: string, err: unknown) => void;
}
interface TaskSnapshot { /* 调试快照 */ }使用示例
import { TaskHub } from '@skyroc/scheduler';
const hub = new TaskHub({
tickInterval: 1000,
onReady: () => console.log('应用启动完成'),
onTaskError: (name, err) => reportError(name, err)
});
hub
.register({
name: 'auth',
type: 'init',
priority: 1,
run: async () => await initAuth()
})
.register({
name: 'permissions',
type: 'init',
priority: 2,
deps: ['auth'], // 必须 auth 完成才能跑
run: async () => await loadPermissions()
})
.register({
name: 'heartbeat',
type: 'periodic',
interval: 30_000,
deps: ['auth'],
run: () => pingServer()
})
.register({
name: 'resize-listener',
type: 'listener',
run: () => window.addEventListener('resize', handleResize),
cleanup: () => window.removeEventListener('resize', handleResize)
});
hub.start();
// hub.pause() / hub.resume() / hub.stop()状态机示意
pending → running ┬─ done (成功)
├─ failed (重试耗尽)
└─ blocked (上游失败)
periodic 任务:done 后回到 pending 等待下个 interval
listener 任务:run 一次后保持 done,stop 时调 cleanup与项目其它包的关系
@skyroc/scheduler 当前是独立基础设施:apps/admin 没有直接使用,但任何需要「应用启动期任务编排」的项目都可以引入。例如:
- 替代
apps/admin/src/bootstrap.tsx里手写的 setupTheme → setupLayouts → setupPlugins → setupI18n 顺序调用; - 把
@skyroc/web-admin-runtime中的 dayjs / nprogress / iconify / app-update 改成 4 个 init 任务; - 取代散在各处的
setInterval心跳。
设计参考
- 单心跳模式来自游戏引擎的「主循环」思想;
- 依赖 + 优先级类似 Kubernetes Init Containers 的 DAG。