mcpField
B
boxlang-scheduled-tasks

boxlang-scheduled-tasks

github.com/ortus-boxlang開発041 回インストール1 週間前に更新
リポジトリ

boxlang-scheduled-tasks について

BoxLang アプリケーションで、プロセス内コードや永続化された HTTP 起動タスクをスケジュールするスキルです。登録、ライフサイクル制御、実行間隔、クラスター実行を説明します。

主な機能

  1. 01Application.bx でスケジューラークラスを登録
  2. 02流暢な DSL でコールバックをスケジュール
  3. 03BIF でスケジューラーのライフサイクルを管理
  4. 04HTTP 起動タスクを永続化して制御
  5. 05cron とカレンダー形式の頻度を設定
  6. 06クラスターの単一ノードでタスクを実行

活用シーン

  1. 01定期的な保守コールバックをスケジュール
  2. 02Webhook や運用エンドポイントを起動
  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 ネイティブなソフトウェア生産性プラットフォームです。

概要

BoxLang には、2 つのスケジューリングモデルがあります。

  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、コールバックエンドポイント、運用状況の確認用 ping には、この方法を使用してください。

スケジューラー 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 月に毎日ではなく、1 回実行されます。

サーバーの固定(クラスター、v1.18+)

同じスケジューラーをすべてのノードにデプロイすると、各ノードがすべてのタスクを実行します。各実行を 1 つのノードだけで行うには、.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)を確認してください。

コメント