@chamvi/频道-cron
Chamvi cron频道:每分一分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每分每一次,每分每分每分每分每分每分每一次,每分每分每分每分每分每一次,每分每分每分每分每分每分每分每一次,每分每分每分每分每分每分一次,一次,每分每分每分每分每分每分每分每分每分每分每.
每个复制品都登记在同一频道。 商店的锁每分一分,
同一套装为库伯内特斯克龙乔布发了一发.
目录
安装
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 通道(它拒绝代理).
| 结果 | status | exitCode |
|---|---|---|
| 运行完成 | completed | 0 |
| 跑步要等批准 | waiting | 0 |
跑步等待跑步暂停等待批准(queue-one(中文(简体) ) | queued | 0 |
| 重叠策略跳过勾选 | skipped | 0 |
| 运行失败或取消 | failed, (中文(简体) ), cancelled | 1 |
暂停审批的跑步不持有吊舱:工作返回,批准得到回答(或时断出),被答复的跑步由长生复制或下个工作吊舱执行,即使自己的滴滴被跳过也会启动引擎. 这个吊舱还恢复了一次运行 吊舱被杀死 并否认批准过他们的超时。 洞穴:
engine.start()追回和执行 每个 已排队运行 每个 代理在共享商店, 不仅仅是克龙运行.drain()中断任何仍在运行的drainTimeoutMs。 。 。 .runJob等待它发送的运行, 所以剩余运行完成 由长寿的复制品 或后期的工作舱, 在该舱内drainTimeoutMs。 。 。 .- 大小
drainTimeoutMs更喜欢长期部署cronChannel()当运行是漫长的.
选项
cronChannel(options)数字 :
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
name | string | 'cron' | 频道名称; on() 认购 |
owner | string | `${hostname}-${pid}` | 锁主 |
lockTtlMs | number | 600_000 | 抓住一滴锁键多久; 迟或迟发射一滴 |
onError | (error, { agent, subscription }) => void | console.error | 失败的勾选和代理文件夹的不可更改订阅 |
cron.on(expression, options)数字 :
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
timezone | string | 本地区域 | IANA区 |
overlap | 'skip' | 'queue-one' | 'allow' | 'skip' | 见 重叠政策 |
payload | unknown | { scheduledAt } | 跑者的有效载荷 |
id | string | `cron:${expression}` | 订阅 id, 每个代理独有 |
runJob(options)数字 :
| 选项 | 类型 | 默认 | 说明 |
|---|---|---|---|
engine | IEngine | 所需经费 | 尚未开始; 开始时没有渠道, 并且被工作耗尽, 也当勾选跳过时。 它的钟给 scheduledAt 并驱动民意调查 |
agent | Agent | 所需经费 | 开枪的特工 |
subscription | string | 唯一的 crun 订阅 | Cron 订阅 ID; 当代理机有多个时需要 |
pollMs | number | 1_000 | 选票 engine.getRun,它也看到运行完成 由另一个复制 |
drainTimeoutMs | number | 30_000 | 传到 engine.drain() |
signal | AbortSignal | 无 | 停止任务( 参见类型文件) |
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。 。 。 .