Skyroc Admin Docs
@core 基础设施

@skyroc/scheduler

协作式任务调度中枢,统一管理初始化 / 周期 / 监听三类任务

概览

包名@skyroc/scheduler
版本1.0.0
依赖(零运行时依赖)
测试✅ 1 个 task-hub.test.ts

@skyroc/scheduler 提供一个单一心跳(setInterval)的协作式调度器,把分散的初始化逻辑、周期任务、事件监听全部收拢到一处管理。它解决「应用启动期 N 个 useEffect、N 个 setInterval、N 个监听器」造成的难以治理的副作用泥潭。

三类任务

类型触发时机典型场景
init启动时执行一次,支持依赖 + 优先级拉取用户信息、初始化主题、加载菜单
periodicinterval 周期执行心跳、token 续期、轮询通知
listener启动时 run() 注册监听,关闭时 cleanup() 释放window 事件、订阅推送

核心特性

特性说明
单心跳全局一个 setInterval(tickInterval) 检查所有任务,避免散落的定时器
依赖图deps: string[] 声明前置任务,DAG 拓扑保证顺序
优先级同层任务按 priority 排序
指数退避失败自动重试,baseRetryDelay * 2^attempt,超过 maxRetries 标记 failed
级联阻塞依赖失败的下游任务标记 blocked,不再尝试
onReady 回调所有 init 完成时触发,方便启动后续流程

默认参数

常量
tickInterval1000ms
maxRetries3
baseRetryDelay1000ms(指数退避基线)
periodic 默认 interval5000ms

类型导出

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。

On this page