# バッチ設計書 11-Ci::ScheduleBulkDeleteJobArtifactCronWorker

## 概要

本ドキュメントは、GitLabにおけるジョブアーティファクトの一括削除をスケジュールするCronワーカー `Ci::ScheduleBulkDeleteJobArtifactCronWorker` の設計仕様を定義する。

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

本バッチは、期限切れのCIジョブアーティファクトを効率的に削除するためのスケジューリングおよびバケット管理を行う。大規模なGitLabインスタンスにおいて、大量のアーティファクトを並列処理で削除するための調整役として機能する。

**業務上の目的・背景**：CIパイプラインの実行により生成されるジョブアーティファクトは、ストレージを大量に消費する可能性がある。有効期限が切れたアーティファクトを適切に削除することで、ストレージコストを削減し、システムのパフォーマンスを維持する。従来の単一ワーカーによる削除では処理が追いつかないため、バケット分割による並列処理アーキテクチャを採用している。

**バッチの実行タイミング**：Cronジョブとして定期的に実行される（通常は数分間隔）。Feature flag `bulk_delete_job_artifacts` が有効な場合のみ動作する。

**主要な処理内容**：
1. Feature flagの確認と早期リターン
2. 停滞（stale）したバケットの回復処理
3. 欠落しているバケットの補充
4. `Ci::BulkDeleteExpiredJobArtifactsWorker` の並列実行をトリガー
5. 処理結果のメタデータログ出力

**前後の処理との関連**：本バッチは `Ci::BulkDeleteExpiredJobArtifactsWorker` の親ワーカーとして機能する。子ワーカーが実際のアーティファクト削除を担当し、本バッチはバケット管理とスケジューリングを担当する。

**影響範囲**：`ci_job_artifacts` テーブル、Redisのバケット管理キー、オブジェクトストレージに保存されたアーティファクトファイル。

## バッチ種別

データクレンジング / リソース管理

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 数分間隔（Cronジョブ） |
| 実行時刻 | 定期実行 |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | cron |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Feature flag | `bulk_delete_job_artifacts` がインスタンスレベルで有効であること |
| Redis接続 | バケット管理のためにRedis SharedStateへのアクセスが可能であること |

### 実行可否判定

Feature flag `bulk_delete_job_artifacts` が無効の場合、即座にリターンし処理をスキップする。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| なし | - | - | - | 本ワーカーはパラメータを受け取らない |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| Redis SharedState | Key-Value | バケット管理情報（available_buckets, occupied_buckets） |
| Feature flag | Boolean | bulk_delete_job_artifacts の有効状態 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| Redis SharedState | Set/SortedSet | バケット状態の更新 |
| Sidekiqジョブキュー | Job | 子ワーカーのエンキュー |
| ログ | JSON | 処理結果メタデータ |

### 出力ファイル仕様

ファイル出力なし。

## 処理フロー

### 処理シーケンス

```
1. Feature flag確認
   └─ bulk_delete_job_artifacts が無効ならリターン
2. 最大バケット数の取得
   └─ max_running_jobs_limit から取得（5または10）
3. 停滞バケットの回復
   └─ 10分以上経過したoccupiedバケットをavailableに戻す
4. 欠落バケットの補充
   └─ available + occupied に含まれないバケットを追加
5. 子ワーカーの実行
   └─ BulkDeleteExpiredJobArtifactsWorker.perform_with_capacity
6. メタデータログ出力
   └─ バケット状態をログに記録
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B{Feature flag有効?}
    B -->|No| C[リターン]
    B -->|Yes| D[最大バケット数取得]
    D --> E[停滞バケット回復]
    E --> F[欠落バケット補充]
    F --> G[子ワーカー実行]
    G --> H[メタデータログ出力]
    H --> I[バッチ終了]
    C --> I
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| バケット管理 | Redis | READ/WRITE | バケット状態の管理 |

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

本ワーカー自体はデータベースに直接アクセスしない。Redis SharedStateを使用してバケット管理を行う。

#### Redis キー

| 操作 | キー名 | 説明 |
|-----|-------|------|
| READ/WRITE | {bulk_delete_expired_job_artifacts}:available_buckets | 利用可能なバケットのSet |
| READ/WRITE | {bulk_delete_expired_job_artifacts}:occupied_buckets | 使用中バケットのSortedSet |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Redis接続エラー | Redis接続失敗 | Sidekiqによるリトライ |
| - | Feature flag評価エラー | Feature flag評価失敗 | エラーログ出力後、次回実行を待つ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqデフォルト |
| リトライ間隔 | 指数バックオフ |
| リトライ対象エラー | Redis接続エラー等 |

### 障害時対応

バッチ失敗時は次回のCron実行を待つ。停滞バケットは自動回復機能により10分後に再利用可能となる。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | Redis multi/execによるアトミック操作 |
| コミットタイミング | 各操作完了時 |
| ロールバック条件 | Redis操作失敗時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | バケット数分（最大10） |
| 目標処理時間 | 数秒以内 |
| メモリ使用量上限 | 最小限（バケットメタデータのみ） |

## 排他制御

本ワーカーはidempotent（冪等）として設計されており、同時実行されても安全に動作する。Redisのアトミック操作（SPOP, ZADD, MULTI/EXEC）により排他制御を実現。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | Sidekiqワーカー開始時 | ジョブID、ワーカー名 |
| 終了ログ | バッチ終了時 | max_buckets, available_count, occupied_count, stale_count, missing_count |
| エラーログ | エラー発生時 | 例外情報 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | 60秒 | 運用チーム |
| エラー件数 | 連続3回失敗 | 運用チーム |

## 備考

- Feature flag `bulk_delete_job_artifacts_high_concurrency` により、並列度（max_buckets）を5から10に変更可能
- バケットはproject_idとjob_idのMOD演算で分散され、並列ワーカー間で処理対象が重複しない設計
