# バッチ設計書 105-ServiceDesk::CustomEmailVerificationCleanupWorker

## 概要

本ドキュメントは、サービスデスクのカスタムメール検証プロセスで期限切れとなった検証を失敗としてマークするバッチ処理「ServiceDesk::CustomEmailVerificationCleanupWorker」の設計内容を記載する。

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

**業務上の目的・背景**：GitLabのサービスデスク機能では、カスタムメールアドレスを設定する際にメール検証が必要となる。検証プロセスは一定期間内に完了する必要があり、期限を過ぎた検証は失敗として扱う必要がある。本バッチは、検証開始後に期限を過ぎた（検証メールが受信されなかった）検証を自動的に失敗としてマークし、検証結果メールを送信することで、検証プロセスを確実に完了させることを目的としている。

**バッチの実行タイミング**：Cronジョブとして定期的に実行される。検証開始済みかつ期限切れ（overdue）の検証を対象とする。

**主要な処理内容**：
1. 検証開始済み（started）かつ期限切れ（overdue）のカスタムメール検証を検索（最大2400件）
2. 各検証に対してCustomEmailVerifications::UpdateServiceを呼び出す
3. 検証結果（失敗）をマークし、結果通知メールを送信

**前後の処理との関連**：本バッチの前段として、サービスデスクのカスタムメール設定時にCustomEmailVerificationが作成される。CustomEmailVerifications::UpdateServiceは検証ステータスの更新と結果通知メールの送信を担当する。

**影響範囲**：service_desk_custom_email_verificationsテーブル、メール送信機能、サービスデスク設定画面に影響する。

## バッチ種別

データクレンジング / ステータス更新

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 定期実行（Cronjob） |
| 実行時刻 | システム設定による |
| 実行曜日 | 毎日 |
| 実行日 | 該当なし |
| トリガー | cron |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| 検証の存在 | 検証開始済みかつ期限切れの検証が存在すること |
| プロジェクトの存在 | 検証に関連するプロジェクトが存在すること |

### 実行可否判定

- started状態かつoverdue（期限切れ）のCustomEmailVerificationが対象
- 最大2400件まで処理（次回実行で残りを処理）

## 入力仕様

### 入力パラメータ

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

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| service_desk_custom_email_verifications | DB | 検証開始済みかつ期限切れの検証情報 |
| projects | DB | 検証に関連するプロジェクト情報 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| service_desk_custom_email_verifications | DB | 検証ステータスを失敗に更新 |
| メール | Email | 検証結果通知メールを送信 |

### 出力ファイル仕様

該当なし

## 処理フロー

### 処理シーケンス

```
1. 対象検証取得
   └─ CustomEmailVerification.started.overdue.limit(2400) で対象取得
2. 各検証の処理
   └─ find_each で順次処理
3. コンテキスト設定
   └─ with_context(project:) でプロジェクトコンテキスト設定
4. 更新サービス呼び出し
   └─ CustomEmailVerifications::UpdateService.execute を実行
      - mail: nil パラメータで検証失敗をマーク
5. 検証結果通知
   └─ UpdateServiceが検証結果メールを送信
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[期限切れ検証取得（最大2400件）]
    B --> C{検証あり?}
    C -->|なし| G[バッチ終了]
    C -->|あり| D[各検証を処理]
    D --> E[UpdateService実行]
    E --> F{次の検証?}
    F -->|あり| D
    F -->|なし| G
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 検証取得 | service_desk_custom_email_verifications | SELECT | 期限切れ検証を取得 |
| ステータス更新 | service_desk_custom_email_verifications | UPDATE | 検証ステータスを失敗に更新 |

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

#### service_desk_custom_email_verifications

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, project_id, state | state = 'started' AND 期限切れ条件 | LIMIT 2400 |
| UPDATE | state, updated_at | state = 'failed' (UpdateService経由) | |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | StandardError | UpdateService実行エラー | Sidekiq標準リトライで対処 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiq標準（25回） |
| リトライ間隔 | 指数バックオフ |
| リトライ対象エラー | すべての例外 |

### 障害時対応

冪等性（idempotent!）が宣言されているため、リトライしても問題ない。UpdateServiceは同じ検証に対して複数回呼び出されても安全に処理される。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | 各検証単位（UpdateService内） |
| コミットタイミング | 各UpdateService完了時 |
| ロールバック条件 | UpdateService内でエラー発生時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 最大2400件/実行 |
| 目標処理時間 | 2分以内（50ms/件 × 2400件） |
| メモリ使用量上限 | 特に制限なし（find_eachで制御） |

## 排他制御

特に排他制御は実装されていない。冪等性が保証されているため、同時実行されても問題ない。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 開始ログ | バッチ開始時 | Sidekiq標準ログ |
| 終了ログ | バッチ終了時 | Sidekiq標準ログ |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 実行状況 | Sidekiq標準監視 | 運用チーム |
| 処理件数 | 異常に多い場合 | 運用チーム |

## 備考

- feature_category: service_desk
- data_consistency: sticky
- idempotent!: 冪等ワーカー
- 処理件数上限は2400件（50ms/件で2分以内に収まる想定）
- UpdateServiceはmail: nilパラメータで呼び出され、検証メールが受信されなかったことを示す
- with_contextでプロジェクトコンテキストを設定し、ログやモニタリングで追跡可能にする
- 残りの検証は次回のCron実行で処理される
