# バッチ設計書 7-Ci_TimedOutBuilds_DropTimedOutWorker

## 概要

本ドキュメントは、タイムアウトしたビルドを削除するバッチ処理「Ci::TimedOutBuilds::DropTimedOutWorker（実装名：Ci::TimedOutBuilds::DropRunningWorker）」の設計仕様を記載する。

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

Ci::TimedOutBuilds::DropRunningWorkerは、明示的にタイムアウト設定がされているCIジョブのうち、設定されたタイムアウト時間を超過したジョブを検出し、失敗（failed）状態に変更するバッチ処理である。ジョブレベルのタイムアウト（`timeout`キーワード）を超過したジョブを強制終了する。

**業務上の目的・背景**：CI/CDパイプラインでは、各ジョブに対してタイムアウト時間を設定できる（.gitlab-ci.ymlの`timeout`キーワード）。これにより、無限ループやハングアップしたジョブが永遠に実行され続けることを防止できる。本バッチは、設定されたタイムアウト時間を超過したジョブを検出し、`job_execution_timeout`を理由として失敗させる。これはStuckCiJobsWorker系（1時間固定）とは異なり、ジョブごとの設定されたタイムアウト値に基づいて判定する。

**バッチの実行タイミング**：10分間隔で実行（cron: `*/10 * * * *`）。高頻度で実行することで、タイムアウトしたジョブを迅速に検出・終了する。

**主要な処理内容**：
1. 各CIパーティションについて、タイムアウト時間を超過したビルドを検索
2. `timed_out_builds`スコープでタイムアウト判定（ジョブ個別のtimeout設定を考慮）
3. 検出されたビルドを100件ずつバッチ処理で失敗状態に更新
4. failure_reasonとして`job_execution_timeout`を設定

**前後の処理との関連**：本ワーカーはStuckCiJobsWorker系とは独立して動作する。StuckCiJobsWorker系は「更新がない」ビルドを対象とし、本ワーカーは「タイムアウト設定を超過した」ビルドを対象とする。DropRunningWorkerは本ワーカーの対象を除外（not_timed_out_builds）することで、役割を分担している。

**影響範囲**：タイムアウト設定のあるCI/CDジョブに影響。ジョブが失敗状態に変更されることで、パイプラインの状態が更新され、関連する通知やステータス表示に影響する。

## バッチ種別

データクレンジング / システムメンテナンス

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 10分間隔 |
| 実行時刻 | 毎時0分、10分、20分、30分、40分、50分 |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | cron (`*/10 * * * *`) |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| タイムアウトビルド存在 | 設定されたタイムアウト時間を超過したビルドが存在すること |

### 実行可否判定

特別な前提条件なし。cronに従い常に実行される。`deduplicate :until_executed, ttl: 30.minutes`により重複実行は防止される。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| なし | - | - | - | cronジョブとして引数なしで実行 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| ci_builds | DB | CIビルドテーブル |
| ci_partitions | DB | CIパーティション管理テーブル |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| ci_builds | DB | ステータス更新（failed）、failure_reason設定 |

### 出力ファイル仕様

ファイル出力なし。

## 処理フロー

### 処理シーケンス

```
1. ログ出力
   └─ "Cleaning timed-out builds"をAppLoggerに出力
2. パーティションループ
   └─ Ci::Partition.find_eachで各パーティションを処理
3. タイムアウトビルド取得
   └─ Ci::Build.timed_out_builds.in_partition(partition.id)
4. バッチドロップ処理
   └─ drop(builds, failure_reason: :job_execution_timeout)
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[パーティション取得]
    B --> C{パーティション存在?}
    C -->|なし| G[バッチ終了]
    C -->|あり| D[タイムアウトビルド検索]
    D --> E{ビルド存在?}
    E -->|なし| F{次のパーティション?}
    E -->|あり| H[ビルドをdrop処理]
    H --> F
    F -->|あり| C
    F -->|なし| G
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| パーティション取得 | ci_partitions | SELECT | 全パーティションを取得 |
| タイムアウトビルド取得 | ci_builds | SELECT | タイムアウト設定を超過したビルドを取得 |
| ビルドステータス更新 | ci_builds | UPDATE | statusをfailedに更新 |

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

#### ci_builds

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | 全カラム | timed_out_buildsスコープ | パーティション別、バッチサイズ100件 |
| UPDATE | status, failure_reason | failed, job_execution_timeout | drop!メソッドで更新 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | StandardError | ビルドdrop処理中のエラー | doom!で代替処理、エラートラッキング |
| - | OptimisticLockingエラー | 同時更新の競合 | 3回リトライ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 3回（OptimisticLocking） |
| リトライ間隔 | 即時 |
| リトライ対象エラー | OptimisticLockingエラー |

### 障害時対応

1. ビルドdrop失敗の場合：doom!メソッドで強制終了状態にマーク
2. エラー発生の場合：Gitlab::ErrorTrackingでSentryに報告

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | レコード単位 |
| コミットタイミング | 各ビルドのdrop!完了時 |
| ロールバック条件 | drop!処理中のエラー発生時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | バッチサイズ100件ずつ処理 |
| 目標処理時間 | 10分以内（次の実行前に完了） |
| メモリ使用量上限 | バッチサイズ100件による制御 |

## 排他制御

- `deduplicate :until_executed, ttl: 30.minutes`による重複実行防止
- ExclusiveLeaseは使用しない（idempotent!により冪等性で対応）

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | サービス開始時 | "Cleaning timed-out builds" |
| 進捗ログ | ビルドdrop時 | "Dropping outdated build", build_id, runner_id, status, failure_reason |
| エラーログ | エラー発生時 | 例外情報、build詳細 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | 10分超過 | 運用チーム |
| エラー件数 | 多発時 | 運用チーム |
| 削除ジョブ数 | 異常増加時 | 運用チーム |

## 備考

- `idempotent!`が設定されており、冪等性が保証されている
- `data_consistency :sticky`が設定されており、レプリカDBの読み取りが許可されている
- `queue_namespace :timed_out_builds`でキューが分離されている
- `deduplicate :until_executed, ttl: 30.minutes`で重複実行を防止
- failure_reasonは`job_execution_timeout`（ジョブ実行タイムアウト）を使用
- StuckBuilds系とは異なる判定ロジック：ジョブ個別のtimeout設定に基づく
- cron設定: `*/10 * * * *` で10分間隔の高頻度実行
