boxlang-scheduled-tasks について
BoxLang アプリケーションで、プロセス内コードや永続化された HTTP 起動タスクをスケジュールするスキルです。登録、ライフサイクル制御、実行間隔、クラスター実行を説明します。
主な機能
- 01Application.bx でスケジューラークラスを登録
- 02流暢な DSL でコールバックをスケジュール
- 03BIF でスケジューラーのライフサイクルを管理
- 04HTTP 起動タスクを永続化して制御
- 05cron とカレンダー形式の頻度を設定
- 06クラスターの単一ノードでタスクを実行
活用シーン
- 01定期的な保守コールバックをスケジュール
- 02Webhook や運用エンドポイントを起動
- 03スケジューラーインスタンスを確認・制御
- 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 つのスケジューリングモデルがあります。
- スケジューラー DSL(インプロセスのコード実行)。
BaseSchedulerとScheduledTaskを基盤とするスケジューラークラスを使用します。 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)を確認してください。