# バッチ設計書 11-Trigger.Cron

## 概要

本ドキュメントは、Jenkins における Trigger.Cron バッチの設計書である。このバッチは PeriodicWork を継承し、毎分実行されることで、ジョブに設定された cron 式に基づくトリガー（TimerTrigger、SCMTrigger 等）を評価・実行する。

### 本バッチの処理概要

Trigger.Cron は Jenkins のスケジューラコアとして機能し、すべての時間ベーストリガーの評価と実行を担う重要なバッチ処理である。

**業務上の目的・背景**：CI/CD パイプラインにおいて、ビルドやテストの自動実行は必須要件である。開発チームが設定した cron 式に基づき、定期的なビルド実行や SCM ポーリングを確実に行う必要がある。このバッチがなければ、時間ベースの自動化が一切機能しなくなり、継続的インテグレーションの根幹が損なわれる。

**バッチの実行タイミング**：毎分実行（60秒間隔）。初回実行は現在の分が終了するタイミングに合わせて調整される（getInitialDelay により秒数を調整）。

**主要な処理内容**：
1. 現在時刻を取得し、カレンダーオブジェクトを更新
2. すべての TriggeredItem（トリガーを持つジョブ）を走査
3. 各ジョブの各トリガーについて、cron 式と現在時刻を照合
4. cron 式がマッチした場合、対応するトリガーの run() メソッドを呼び出し
5. 同期ポーリングモードが有効な場合、SCMTrigger は依存関係順に処理
6. トリガー実行時間が閾値（デフォルト30秒）を超過した場合、警告ログを出力し SlowTriggerAdminMonitor に報告

**前後の処理との関連**：このバッチは独立して動作するが、トリガーの実行結果として TimerTrigger はビルドキューへのジョブ追加を、SCMTrigger は SCM ポーリング処理の起動を行う。後続処理としてビルド実行が開始される。

**影響範囲**：Jenkins に登録されたすべてのジョブのトリガー設定に影響する。トリガーが正常に動作しない場合、自動ビルドが実行されず、CI/CD パイプラインが停止する重大な影響がある。

## バッチ種別

トリガー実行 / スケジューラ処理

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 毎分（1分間隔） |
| 実行時刻 | 毎分0秒（初回は調整あり） |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | PeriodicWork（内部タイマー） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Jenkins起動済み | Jenkins インスタンスが起動し、PeriodicWork スケジューラが動作していること |
| ジョブ設定済み | トリガー設定を持つジョブが少なくとも1つ存在すること |

### 実行可否判定

PeriodicWork として自動的に実行される。実行可否判定は特に行われず、毎分必ず実行される。個々のトリガーについては、cron 式との照合結果により実行が決定される。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| CRON_THRESHOLD | long | No | 30 | トリガー実行の警告閾値（秒）。システムプロパティで設定可能 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| Jenkins.allItems(TriggeredItem.class) | Java オブジェクト | トリガー設定を持つ全ジョブのリスト |
| Trigger.tabs (CronTabList) | Java オブジェクト | 各トリガーに設定された cron 式の解析結果 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| ビルドキュー | Java オブジェクト | TimerTrigger によるビルドスケジュール |
| SCM ポーリングキュー | Java オブジェクト | SCMTrigger によるポーリングタスク |
| ログファイル | テキスト | 処理結果のログ出力 |

### 出力ファイル仕様

バッチ自体はファイル出力を行わないが、トリガー実行結果は Jenkins のログに出力される。

| 項目 | 内容 |
|-----|------|
| ファイル名 | jenkins.log |
| 出力先 | JENKINS_HOME/logs/ |
| 文字コード | UTF-8 |
| 区切り文字 | 改行 |

## 処理フロー

### 処理シーケンス

```
1. doRun() メソッド開始
   └─ Cron クラスの doRun() が PeriodicWork により呼び出される
2. 現在時刻の確認
   └─ カレンダーオブジェクトと現在時刻を比較し、未処理の分を検出
3. checkTriggers(cal) の呼び出し
   └─ 検出した各分について checkTriggers を実行
4. 同期ポーリングモードのチェック
   └─ SCMTrigger.DescriptorImpl.synchronousPolling が true の場合、専用処理を実行
5. 全 TriggeredItem の走査
   └─ Jenkins.get().allItems(TriggeredItem.class) で全ジョブを取得
6. 各トリガーの cron 式チェック
   └─ t.tabs.check(cal) で現在時刻とのマッチングを確認
7. トリガー実行
   └─ マッチした場合、t.run() を呼び出し
8. 実行時間の監視
   └─ CRON_THRESHOLD を超過した場合、警告を出力
9. カレンダーを1分進める
   └─ cal.add(Calendar.MINUTE, 1) で次の分へ
```

### フローチャート

```mermaid
flowchart TD
    A[Cron.doRun 開始] --> B{現在時刻 >= カレンダー時刻?}
    B -->|No| Z[処理終了]
    B -->|Yes| C[checkTriggers 呼び出し]
    C --> D{同期ポーリングモード?}
    D -->|Yes| E[SCMTrigger を依存関係順に処理]
    D -->|No| F[全 TriggeredItem を走査]
    E --> F
    F --> G{次のジョブあり?}
    G -->|No| H[カレンダーを1分進める]
    G -->|Yes| I{次のトリガーあり?}
    I -->|No| G
    I -->|Yes| J{cron 式がマッチ?}
    J -->|No| I
    J -->|Yes| K[トリガー実行 t.run]
    K --> L{実行時間 > 閾値?}
    L -->|Yes| M[警告ログ出力]
    L -->|No| I
    M --> I
    H --> B
```

## データベース操作仕様

### 操作別データベース影響一覧

このバッチはデータベース操作を直接行わない。Jenkins の内部データ構造（メモリ上のジョブ設定）を参照するのみ。

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| - | - | - | データベース操作なし |

### テーブル別操作詳細

該当なし

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | RuntimeException | トリガーの run() メソッドで例外発生 | ログに警告を出力し、他のトリガー処理を継続 |
| - | IllegalArgumentException | cron 式のパースエラー | 警告ログを出力し、該当トリガーをスキップ |
| - | Throwable | checkTriggers 内での予期せぬ例外 | ログに警告を出力し、カレンダーを進めて次回処理を継続 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

リトライは行わない。次回の定期実行（1分後）で再度処理される。

### 障害時対応

1. 個別トリガーの失敗: ログを確認し、該当ジョブの cron 式設定を見直す
2. 全体的な処理遅延: SlowTriggerAdminMonitor でアラートが表示されるため、重いトリガー処理を特定して最適化
3. Cron バッチ自体の停止: Jenkins を再起動し、PeriodicWork スケジューラを復旧

## トランザクション仕様

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | トランザクション管理なし |
| コミットタイミング | - |
| ロールバック条件 | - |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 数百〜数千ジョブ |
| 目標処理時間 | 60秒以内（次回実行までに完了） |
| メモリ使用量上限 | 特に制限なし（Jenkins ヒープ内） |

## 排他制御

- 同一インスタンス内では PeriodicWork により単一スレッドで実行される
- 同期ポーリングモード有効時、前回の同期ポーリングが完了していない場合は新規ポーリングをスキップ
- previousSynchronousPolling フラグで制御

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| FINE | 毎分の処理開始時 | "cron checking {時刻}" |
| FINER | 各ジョブ検査時 | "considering {ジョブ}" / "found trigger {トリガー}" |
| CONFIG | トリガー発火時 | "cron triggered {ジョブ}" |
| WARNING | 実行時間超過時 | "Trigger '{名前}' triggered by '{ジョブ}' spent too much time..." |
| WARNING | 例外発生時 | "{トリガークラス}.run() failed for {ジョブ}" |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| トリガー実行時間 | 30秒（CRON_THRESHOLD） | SlowTriggerAdminMonitor（管理画面表示） |
| SCM ポーリングキュー滞留 | STARVATION_THRESHOLD（1時間） | AdministrativeMonitorImpl |

## 備考

- Trigger.Cron は @Extension @Symbol("cron") アノテーションにより自動登録される
- カレンダーオブジェクトは秒とミリ秒を0に設定し、分単位で処理を行う
- getInitialDelay() により、初回実行は現在の分が終了するタイミングに調整される
- Jenkins 2.289 以降、CRON_THRESHOLD の単位がミリ秒から秒に変更された
