mcpField
B
boxlang-scheduled-tasks

boxlang-scheduled-tasks

github.com/ortus-boxlang开发041 次安装1 周前更新
代码仓库

关于 boxlang-scheduled-tasks

面向 BoxLang 应用的定时任务技能,涵盖进程内代码调度和持久化 HTTP 触发任务,并说明注册、生命周期控制、频率设置及集群执行。

主要功能

  1. 01在 Application.bx 注册调度器类
  2. 02用流式 DSL 调度回调任务
  3. 03通过 BIF 管理调度器生命周期
  4. 04持久化并控制 HTTP 触发任务
  5. 05配置 cron 与日历频率
  6. 06将任务限定在集群单节点运行

适用场景

  1. 01安排周期性维护回调
  2. 02触发 webhook 或运维端点
  3. 03检查或控制调度器实例
  4. 04避免集群节点重复执行任务

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ortus-boxlang/skills --skill boxlang-scheduled-tasks

安装后在 Claude Code 中输入/boxlang-scheduled-tasks确认已加载。

详细介绍

BoxLang 定时任务

BoxLang 是一个 AI 原生的软件生产力平台,用于构建、现代化改造和运行应用,让开发者与 AI Agent 携手协作。

概览

BoxLang 提供两种调度模式:

  1. 调度器 DSL(进程内代码执行):使用由 BaseScheduler 和 ScheduledTask 支持的调度器类
  2. bx:schedule 组件(HTTP 驱动的任务):用于创建/更新/删除/暂停/恢复/列出/运行任务的端点

对于丰富的进程内逻辑和任务回调,请使用调度器 DSL。对于简单的持久化 URL 触发器,请使用 bx:schedule。

Application.bx 集成

你可以直接在 Application.bx 中注册调度器类,以便它们在应用上下文中自动发现。

有关完整的描述符行为(应用发现、多应用隔离、生命周期),请参阅 application-descriptor。

class {

    this.name = "MyApp"

    // Auto-register scheduler classes for this application
    this.schedulers = [
        "schedulers.DailyMaintenance",
        "schedulers.HourlyReports"
    ]

}

当调度器生命周期应由应用启动/关闭管理,而非通过临时调用 schedulerStart() 管理时,请使用此方式。

选项 1:调度器 DSL(代码工作负载推荐)

调度器类封装 BaseScheduler,并在 configure() 中以流畅方式注册任务。

class {

    property name="scheduler"
    property name="logger"

    function configure() {
        scheduler
            .setSchedulerName( "reporting-scheduler" )
            .setTimezone( "America/Chicago" )

        scheduler.task( "daily-report", "reports" )
            .call( () => generateDailyReport() )
            .everyDayAt( "02:00" )
            .onFailure( ( task, exception ) => {
                logger.error( "Task #task.getName()# failed: #exception.message#" )
            } )
    }

}
注册和启动调度器类
// Start from class path (creates, configures, registers, and starts)
schedulerStart( className = "schedulers.ReportingScheduler", name = "reporting", force = true )

// Lookup / control
schedulerGet( "reporting" )
schedulerStats( "reporting" )
schedulerRestart( "reporting", force = false, timeout = 30 )
schedulerShutdown( "reporting", force = false, timeout = 30 )

选项 2:bx:schedule 组件(HTTP 驱动)

bx:schedule 会持久化任务定义(默认路径:${boxlang-home}/config/tasks.json),并执行定时 HTTP GET 请求。

bx:schedule action="create"
    task="nightlyCleanup"
    url="https://myapp.example/tasks/cleanup"
    cronTime="0 2 * * *";

bx:schedule action="pause" task="nightlyCleanup";
bx:schedule action="run" task="nightlyCleanup";
bx:schedule action="delete" task="nightlyCleanup";

此方式适用于 Webhook、回调端点和运维探测。

调度器 BIF

核心调度器生命周期 BIF:

  • schedulerStart( className, name?, force=true )
  • schedulerGet( name )
  • schedulerGetAll()
  • schedulerList()
  • schedulerStats( name? )
  • schedulerRestart( name, force=false, timeout=30 )
  • schedulerShutdown( name, force=false, timeout=30 )

说明:

  • schedulerStart() 会实例化 BoxLang 类,将其封装在 BoxScheduler 中,调用 configure(),然后注册并启动它。
  • schedulerRestart() 和 schedulerShutdown() 会验证调度器是否存在;若不存在则抛出异常。

任务注册模式

使用有意义的名称和可选分组,以便清晰地进行运维管理。

scheduler.task( "cleanup-expired-sessions", "maintenance" )
    .call( () => cleanupSessions() )
    .every( 15, "minutes" )

scheduler.task( "send-weekly-digest", "notifications" )
    .call( () => sendDigest() )
    .everyWeekOn( "Monday", "08:30" )

注册时禁用,便于调试:

scheduler.xtask( "experimental-task", "debug" )
    .call( () => runExperiment() )
    .everyMinute()

常用频率 API

  • every( period, timeUnit )
  • spacedDelay( delay, timeUnit )(无重叠模式)
  • cron( expression )
  • everySecond()、everyMinute()、everyHour()、everyHourAt( minute )
  • everyDay()、everyDayAt( "HH:mm" )
  • everyWeek()、everyWeekOn( day, time )
  • everyMonth()、everyMonthOn( day, time )
  • everyYear()、everyYearOn( month, day, time )
  • onWeekdays( time )、onWeekends( time )

everyMonthOn( day ) 会在较短月份中将日期调整为当月最后一天(v1.18+),因此 everyMonthOn( 31 ) 在 2 月会运行一次,而不是每天运行。

服务器固定(集群,v1.18+)

当同一调度器部署到每个节点时,每个节点都会运行所有任务。调用 .onOneServer(),即可让每次执行只由一个节点运行。BoxLang 使用调度器的 cacheName 缓存作为分布式锁,因此请将其指向各服务器共享的缓存(例如通过 bx-redis 使用 Redis)。

task( "nightly-cleanup" )
    .call( () => cleanupOldRecords() )
    .everyDayAt( "02:00" )
    .onOneServer()

调度器 API 支持的时间单位包括:days、hours、minutes、seconds、milliseconds、microseconds、nanoseconds。

Cron 支持

支持的格式:

  • 5 字段 Unix:minute hour day-of-month month day-of-week
  • 6 字段 Quartz:second minute hour day-of-month month day-of-week

示例:

// Every day at 2:00 AM
scheduler.task( "nightly" )
    .call( () => nightlyJob() )
    .cron( "0 2 * * *" )

// Every weekday at 8:30:00 AM
scheduler.task( "weekday-digest" )
    .call( () => digestJob() )
    .cron( "0 30 8 * * MON-FRI" )

最佳实践

  • 始终为调度器设置明确的 name 和 timezone。
  • 使用描述性任务名称和逻辑分组。
  • 保持任务主体精简;将繁重的扇出工作转移到异步执行器。
  • 优先使用 onFailure 钩子和集中式日志记录,以便观察运行情况。
  • 未检查吞吐量前,避免设置过于密集的间隔。
  • 如果任务的运行时间可能超过其间隔,请使用 spacedDelay() 或防止重叠的模式。
  • 对于必须在集群范围内只运行一次的任务,使用 .onOneServer()(v1.18+)。
  • 使用 CLI 检查调度情况:boxlang schedule 和 boxlang schedule --json(v1.18+)。

故障排查

  • 找不到调度器:确认已调用 schedulerStart(),且 schedulerList() 包含该名称。
  • 任务从未触发:检查时区、cron 表达式以及开始/结束约束。
  • 重复运行/运行堆叠:使用间隔控制/防止重叠策略,而非严格的固定频率行为。
  • 任务在每个节点上运行:添加 .onOneServer(),并使用共享的 cacheName(v1.18+)。
  • 静默失败:检查调度器日志输出和 schedulerStats() 计数器(totalFailures、lastResult)。

评论

支持 Markdown