npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@h-ai/scheduler

v0.1.0-alpha.10

Published

Hai Framework task scheduling module with cron, function, and API jobs.

Readme

@h-ai/scheduler

定时任务调度模块,支持统一任务模型、cron 调度、JS 函数字符串 / HTTP API 执行、任务持久化、执行日志查询,以及全局任务生命周期回调。

依赖

  • @h-ai/reldb — 任务定义与执行日志持久化,enableDb: true 时需先初始化
  • @h-ai/cache — 分布式锁,可选;初始化后自动参与定时触发抢锁

快速开始

import { cache } from '@h-ai/cache'
import { reldb } from '@h-ai/reldb'
import { scheduler } from '@h-ai/scheduler'

await reldb.init({ type: 'sqlite', database: './scheduler.db' })
await cache.init({ type: 'memory' }) // 可选

await scheduler.init({
  enableDb: true,
  maxLogs: 1000,
  retentionDays: 30,
  hooks: {
    onTaskStart(event) {
      void event
    },
  },
})

await scheduler.register({
  id: 'health-check',
  name: '健康检查',
  description: '每 5 分钟执行一次系统健康检查',
  cron: '*/5 * * * *',
  params: { channel: 'ops' },
  retry: { maxAttempts: 3, backoffMs: [1000, 5000] },
  handler: {
    kind: 'api',
    url: 'https://api.example.com/health',
    method: 'GET',
    timeout: 10000,
  },
})

await scheduler.register({
  id: 'cleanup',
  name: '清理过期数据',
  description: '每日凌晨执行过期数据清理',
  cron: '0 2 * * *',
  deleteAfterRun: true,
  params: { source: 'nightly' },
  handler: {
    kind: 'js',
    code: '(context) => ({ taskId: context.taskId, params: context.params })',
  },
})

scheduler.start()

const manualResult = await scheduler.trigger('cleanup', { source: 'admin-console' })
const logs = await scheduler.getLogs({
  triggerType: 'manual',
  triggerSource: 'admin-console',
  startedAfter: Date.now() - 24 * 60 * 60 * 1000,
})

scheduler.stop()
await scheduler.close()

统一任务模型

interface TaskDefinition {
  id: string
  name: string
  description?: string
  cron: string
  enabled?: boolean
  deleteAfterRun?: boolean
  retry?: {
    maxAttempts: number
    backoffMs?: number[]
  }
  params?: Record<string, unknown>
  handler?: ApiTaskConfig | JsTaskConfig
}

interface ApiTaskConfig {
  kind: 'api'
  url: string
  method?: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'
  headers?: Record<string, string>
  body?: unknown
  timeout?: number
}

interface JsTaskConfig {
  kind: 'js'
  code: string // JS 函数字符串
  timeout?: number
}

说明:

  • 所有任务都可持久化到数据库,包括 kind: 'js' 的任务
  • JS 任务会在运行时编译,并基于源码做缓存,避免每次触发都重新编译
  • handler 可为空;此时可通过全局 hooks.onTaskExecute 统一执行

任务生命周期回调

初始化时传入或运行时通过 setHooks() 设置:

await scheduler.init({
  enableDb: false,
  hooks: {
    onTaskStart(event) {
      void event
    },
    async onTaskExecute(event) {
      return { via: 'hook', source: event.context.trigger.source }
    },
    onTaskInterrupted(event) {
      void event
    },
    onTaskFinish(event) {
      void event
    },
  },
})

执行日志

查询日志时可按触发来源过滤:

const logs = await scheduler.getLogs({
  taskId: 'cleanup',
  triggerType: 'manual',
  triggerSource: 'admin-console',
  startedAfter: Date.now() - 24 * 60 * 60 * 1000,
  startedBefore: Date.now(),
  pagination: { page: 1, pageSize: 20 },
})

执行日志支持自动清理策略(初始化时配置):

  • maxLogs:最多保留 N 条日志
  • retentionDays:最多保留最近 N 天日志

API 概览

  • init(config?)
  • register(task)
  • unregister(taskId)
  • updateTask(taskId, updates)
  • start() / stop()
  • trigger(taskId, { source? })
  • getLogs(options?)
  • setHooks(hooks) / clearHooks()
  • tasks / hooks / config / isInitialized / isRunning
  • close()

错误处理

所有公共 API(除 close())返回 HaiResult<T>

常用错误码:

| 错误码 | code | 说明 | | ----------------------------------------- | ------------------- | --------------- | | HaiSchedulerError.NOT_INITIALIZED | hai:scheduler:010 | 未初始化 | | HaiSchedulerError.INIT_FAILED | hai:scheduler:011 | 初始化失败 | | HaiSchedulerError.CONFIG_ERROR | hai:scheduler:012 | 配置错误 | | HaiSchedulerError.TASK_NOT_FOUND | hai:scheduler:020 | 任务不存在 | | HaiSchedulerError.TASK_ALREADY_EXISTS | hai:scheduler:021 | 任务已存在 | | HaiSchedulerError.INVALID_CRON | hai:scheduler:022 | Cron 表达式无效 | | HaiSchedulerError.EXECUTION_FAILED | hai:scheduler:023 | 执行失败 | | HaiSchedulerError.JS_EXECUTION_FAILED | hai:scheduler:024 | JS 执行失败 | | HaiSchedulerError.API_EXECUTION_FAILED | hai:scheduler:025 | API 执行失败 | | HaiSchedulerError.DB_SAVE_FAILED | hai:scheduler:026 | DB 保存失败 | | HaiSchedulerError.ALREADY_RUNNING | hai:scheduler:027 | 已在运行 | | HaiSchedulerError.NOT_RUNNING | hai:scheduler:028 | 未在运行 | | HaiSchedulerError.LOCK_ACQUIRE_FAILED | hai:scheduler:029 | 锁获取失败 | | HaiSchedulerError.JS_COMPILE_FAILED | hai:scheduler:030 | JS 编译失败 | | HaiSchedulerError.HOOK_EXECUTION_FAILED | hai:scheduler:031 | Hook 执行失败 |

测试

pnpm --filter @h-ai/scheduler test

License

Apache-2.0