@chamvi/channel-cron

中文文档
0.8.0发布于 2026/11/09Apache-2.0TypeScriptES Module构建来源已验证近 30 天下载 3465

Chamvi cron频道:每分一分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每一次,每分每分每分每分每分每分每一次,每分每分每分每分每分每一次,每分每分每分每分每分每分每分每一次,每分每分每分每分每分每分一次,一次,每分每分每分每分每分每分每分每分每分每分每.

中文使用文档
文档目录10 节
  1. 安装
  2. 使用量
  3. 滴答滴答的动作
  4. 重叠政策
  5. 时区
  6. 关闭
  7. 一发工作
  8. 选项
  9. API 密码
  10. 许可证

@chamvi/channel-cron

@chamvi/频道-cron

Chamvi cron频道:每分一分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每一次,每分每分每分每分每分每分每一次,每分每分每分每分每分每一次,每分每分每分每分每分每分每分每一次,每分每分每分每分每分每分一次,一次,每分每分每分每分每分每分每分每分每分每分每.
每个复制品都登记在同一频道。 商店的锁每分一分,
同一套装为库伯内特斯克龙乔布发了一发.

npm version CI License


目录

安装

npm install @chamvi/channel-cron @chamvi/core --save

仅限无害环境管理,节点.js >=26.0.0。 。 。 . @chamvi/core 是同龄人依赖; hubwire (车内)和 cron-parser 与软件包一起安装.

使用量

cron.on() 订阅 cron 频道的代理; cronChannel() 引擎启动的频道是 :

import type { LanguageModel } from 'ai';
import {
    Engine,
    createMemoryStore,
    defineModelAgent,
} from '@chamvi/core';
import { cron, cronChannel } from '@chamvi/channel-cron';

export async function startScheduling(model: LanguageModel) {
    const sweep = defineModelAgent({
        name: 'sweep',
        model,
        instructions: 'Close stale issues older than 30 days.',
        // every 30 minutes, Berlin time; skipped while the previous run is active
        channels: [cron.on('*/30 * * * *', { timezone: 'Europe/Berlin' })],
    });

    // createMemoryStore is per process; with several replicas, pass one shared store
    // (e.g. createDatabaseStore) so its lock fires each tick once across them
    const engine = new Engine({
        store: createMemoryStore(),
        agents: [sweep],
        // every replica registers the same channel; it reads agents and store from the engine
        channels: [cronChannel()],
    });

    // starts the cron channel after recovering runs
    await engine.start();

    // shutdown: drain() stops the channel first, then lets the runs in flight finish
    // await engine.drain();
    return { engine };
}

cron.on(expression, options?) 验证表达式( cron-parser) 和时区并丢弃 InvalidAgentDefinitionError 对于一个它拒绝. engine.start() 恢复运行后启动频道: 订阅调度器无法使用的代码( 表达式 croner 拒绝) 的代理失败 engine.start() 与 InvalidAgentDefinitionError 命名代理和订阅,代理文件夹的地址是 onError 留下那个特工 其他频道的订阅被忽略. 该频道跟随在运行时间注册,替换并移除的代理.

第二个cron信道(例如每个区域一个)需要自己的名称 on() 只让订阅点火:

const eu = cronChannel({ name: 'cron-eu' });
defineModelAgent({ name: 'digest', channels: [eu.on('0 8 * * *', { timezone: 'Europe/Berlin' })] /* ... */ });
new Engine({ channels: [cronChannel(), eu] /* ... */ });

滴答滴答的动作

  • 每个订阅一个部分. 每一个都变成一个 集线器计划组件 命名 cron:<agent>:<subscriptionId>。 。 。 .
  • 每滴一个复制品. 在滴答运行之前,复制品会获得商店锁 cron:<agent>:<subscriptionId>:<scheduledAt ISO> (通过) ILockRepository用于 lockTtlMs (默认10分). 密钥永远不会被放出:一个晚点放出同一滴的复制品无法再次取胜.
  • 重复发送. 胜者通过频道发送(信封) channel =频道名称, trigger = 有效载荷的订阅id) options.payload ?? { scheduledAt: '<ISO>' } 和独有性键 <subscriptionId>@<scheduledAt ISO>,所以即使同一勾选的第二次射击也返回了现有的运行。 订户自己买的 idempotencyKey() 被忽略为克龙.
  • 从来没有开始. 启动或重新启动复制点火无事可做; 第一次发送是下一个预定的勾选 .
  • 无相接取. 掉入重启的滴答,或者其计时器起火的滴答 lockTtlMs 或更晚(一个已暂停的流程),不会在以后发射.
  • 报告失败,而不是抛出. 锁定存储失败, 重叠检查或发送到达 onError(error, { agent, subscription });下一勾选正常运行.

重叠政策

cron.on(expression, { overlap }) 设置策略; 频道在发送前执行。 "Active"的意思是同一订阅的一跑在 queued, (中文(简体) ), running, (中文(简体) ), waiting 或者说 interrupted。 。 。 .

政策选中值跳过时默认 concurrencyKey
skip (默认)任何订阅运行已激活订阅编号
queue-one订阅的一连串仍然 queued订阅编号
allow永远无

A 类 concurrencyKey() 在订阅时胜过默认。 默认密钥是 queue-one 等待 : 引擎每次启动一次运行, 一次启动密钥, 所以队列运行在活动者和解时启动 。 这也使得比赛变得无害:在之前的滴滴调度还在飞行中时进行检查的勾子可能会发出第二次跑道,然后等待而不是同时跑道.

时区

cron.on(expression, { timezone: 'Europe/Berlin' }) 取IANA区;没有IANA区,则应用过程的局部区. 在 DST 更改时 :

  • 当地时间发生两次(倒回)火灾一次,第一次发生时.
  • 当地时间春前变化跳过火灾一次,一小时后当地时间(30 2 * * * 3点半起火).

关闭

engine.drain() (和 engine.stop())首先停止航道(没有新的滴入;飞行完成时滴入),然后排出跑道:

await engine.drain(); // stops the cron channel, waits for running runs, then interrupts the rest

一发工作

runJob() 开出一次Cron订阅 等待它的运行, 一个Kubernetes CronJob 而不是一个长寿的复制品:

const { exitCode } = await runJob({ engine, agent: sweep });
process.exitCode = exitCode;

它在当前时间发送勾选( 重叠策略适用) , 启动引擎 start({ channels: false }) (所以一个工作从不开始 cron 调度或其他渠道) 并运行一个批准勾选(当勾选被跳过时) , 等待到运行 completed, (中文(简体) ), failed, (中文(简体) ), cancelled 或者说 waiting,或 queued 背着同样的订阅 等待批准,然后打电话 engine.drain()。引擎必须持有订阅的 cron 通道(它拒绝代理).

结果statusexitCode
运行完成completed0
跑步要等批准waiting0
跑步等待跑步暂停等待批准(queue-one(中文(简体) )queued0
重叠策略跳过勾选skipped0
运行失败或取消failed, (中文(简体) ), cancelled1

暂停审批的跑步不持有吊舱:工作返回,批准得到回答(或时断出),被答复的跑步由长生复制或下个工作吊舱执行,即使自己的滴滴被跳过也会启动引擎. 这个吊舱还恢复了一次运行 吊舱被杀死 并否认批准过他们的超时。 洞穴:

  • engine.start() 追回和执行 每个 已排队运行 每个 代理在共享商店, 不仅仅是克龙运行.
  • drain() 中断任何仍在运行的 drainTimeoutMs。 。 。 . runJob 等待它发送的运行, 所以剩余运行完成 由长寿的复制品 或后期的工作舱, 在该舱内 drainTimeoutMs。 。 。 .
  • 大小 drainTimeoutMs 更喜欢长期部署 cronChannel() 当运行是漫长的.

选项

cronChannel(options)数字 :

选项类型默认说明
namestring'cron'频道名称; on() 认购
ownerstring`${hostname}-${pid}`锁主
lockTtlMsnumber600_000抓住一滴锁键多久; 迟或迟发射一滴
onError(error, { agent, subscription }) => voidconsole.error失败的勾选和代理文件夹的不可更改订阅

cron.on(expression, options)数字 :

选项类型默认说明
timezonestring本地区域IANA区
overlap'skip' | 'queue-one' | 'allow''skip'见 重叠政策
payloadunknown{ scheduledAt }跑者的有效载荷
idstring`cron:${expression}`订阅 id, 每个代理独有

runJob(options)数字 :

选项类型默认说明
engineIEngine所需经费尚未开始; 开始时没有渠道, 并且被工作耗尽, 也当勾选跳过时。 它的钟给 scheduledAt 并驱动民意调查
agentAgent所需经费开枪的特工
subscriptionstring唯一的 crun 订阅Cron 订阅 ID; 当代理机有多个时需要
pollMsnumber1_000选票 engine.getRun,它也看到运行完成 由另一个复制
drainTimeoutMsnumber30_000传到 engine.drain()
signalAbortSignal无停止任务( 参见类型文件)

API 密码

导出仁爱目的
cronChannel函数克龙频道; engine.start() 开始, drain() 停下来; .on() 认购
cron对象cron.on(expression, options?): 默认的订阅 cron 频道
runJob函数开出一次Cron订阅 等待运行
fireCronSubscription函数一个勾选符:对某个特定的重复检查和发送 scheduledAt
readCronOptions函数读取并验证选项 cron.on() 订阅存储
assertSchedulable函数丢弃用于订阅 crun 频道( 默认) cron调度器无法使用
createRepositoryScheduleLock函数接线 IScheduleLock 超过核心 ILockRepository
CRON_CHANNEL_NAME常数'cron'
SCHEDULE_LOCK_TTL_MS常数默认锁定 TTL, 600_000

类型 : CronChannel, (中文(简体) ), CronChannelOptions, (中文(简体) ), CronChannelErrorContext, (中文(简体) ), CronSubscriber, (中文(简体) ), CronSubscriptionOptions, (中文(简体) ), OverlapPolicy, (中文(简体) ), RunJobOptions, (中文(简体) ), RunJobResult, (中文(简体) ), CronOptions, (中文(简体) ), CronTickContext, (中文(简体) ), CronTickResult, (中文(简体) ), CronTickDispatched, (中文(简体) ), CronTickSkipped。 。 。 .

许可证

原载 Apache 许可证 2.0。 。 。 .

版本与发布记录

@chamvi/channel-cron 共发布 15 个版本,首次发布于 2026/10/25;过去 12 个月发布了 15 个版本。最新版本附带 npm provenance 构建来源证明,可追溯到公开的 CI 构建记录。

版本发布日期距今
0.8.0latest2026/11/09今天
0.7.32026/11/063 天前
0.7.22026/11/053 天前
0.7.12026/11/054 天前
0.7.02026/11/045 天前
0.6.12026/11/045 天前

关于 @chamvi/channel-cron 的常见问题

@chamvi/channel-cron 是什么?

Chamvi cron频道:每分一分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每一次,每分每分每分每分每分每分每一次,每分每分每分每分每分每一次,每分每分每分每分每分每分每分每一次,每分每分每分每分每分每分一次,一次,每分每分每分每分每分每分每分每分每分每分每.

如何安装 @chamvi/channel-cron?

在项目目录运行 npm install @chamvi/channel-cron,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:@chamvi/core(^0.8.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@chamvi/channel-cron 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@chamvi/channel-cron 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@chamvi/channel-cron 需要什么版本的 Node.js?

package.json 的 engines 字段要求 Node.js >=26.0.0。版本不符时 npm 默认只给出警告,开启 engine-strict 后会拒绝安装。

@chamvi/channel-cron 可以商用吗?

@chamvi/channel-cron 使用 Apache-2.0 许可。宽松许可:允许商业使用、修改和再分发,并附带明确的专利授权;分发时需保留许可与 NOTICE 文件,修改过的文件要注明改动。以上为概括,不构成法律意见,请以许可原文为准。

@chamvi/channel-cron 的下载量有多少?

根据 npm 官方下载统计,@chamvi/channel-cron 在 2026/10/10 – 2026/11/08 这 30 天内被下载 3,465 次,日均约 116 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@chamvi/channel-cron 还在维护吗?

最新版本 0.8.0 发布于 2026/11/09(今天);至今共发布 15 个版本,其中过去 12 个月发布了 15 个;首次发布于 2026/10/25。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。