# バッチ設計書 61-PagesDomainRemovalCronWorker

## 概要

本ドキュメントは、GitLab Pagesのカスタムドメイン削除を管理するバッチ処理（PagesDomainRemovalCronWorker）の設計を記載します。

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

GitLab Pagesのカスタムドメインで削除予定時刻を超過したドメインを自動削除するバッチ処理です。

**業務上の目的・背景**：GitLab Pagesでは、ユーザーがカスタムドメインを設定できますが、ドメインの検証が長期間行われない場合やユーザーが削除を予約した場合、セキュリティとリソース管理の観点からドメインを自動削除する必要があります。本バッチは、削除予定時刻（remove_at）を過ぎたドメインを検出し、安全に削除することで、不正利用の防止とシステムリソースの効率的な利用を実現します。

**バッチの実行タイミング**：日次実行（毎日0:47に実行）

**主要な処理内容**：
1. PagesDomainテーブルから削除対象ドメイン（remove_at < 現在時刻）を検索
2. 各ドメインをプロジェクトコンテキスト付きで処理
3. ドメインレコードを削除（destroy!）
4. エラー発生時はログ記録して次のレコードに継続

**前後の処理との関連**：PagesDomainVerificationCronWorker（ドメイン検証）で検証失敗が続くとremove_atが設定され、本バッチの削除対象となります。

**影響範囲**：pages_domainsテーブル、関連するacme_ordersテーブル、Pagesの静的サイトホスティング

## バッチ種別

データクレンジング / 期限切れリソース削除

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 日次 |
| 実行時刻 | 00:47 |
| 実行曜日 | 毎日 |
| 実行日 | - |
| トリガー | cron |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| GitLab Pagesが有効 | Pagesドメイン機能が利用可能であること |
| データベース接続 | PostgreSQLへの接続が確立されていること |

### 実行可否判定

特別な実行可否判定ロジックはありません。cronスケジュールに従って自動実行されます。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| なし | - | - | - | パラメータなしで実行 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| pages_domains | DB | 削除対象のPagesドメイン情報 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| pages_domains | DB | 削除対象レコードの削除 |
| ログ | ファイル/stdout | 処理結果のログ出力 |

### 出力ファイル仕様

ファイル出力はありません。

## 処理フロー

### 処理シーケンス

```
1. 削除対象ドメインの検索
   └─ PagesDomain.for_removal.with_logging_info で remove_at < Time.current のレコードを取得
2. 各ドメインの処理（find_each）
   └─ プロジェクトコンテキストを設定して domain.destroy! を実行
3. エラーハンドリング
   └─ StandardError発生時はGitlab::ErrorTrackingに記録して次のレコードに継続
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[削除対象ドメイン検索<br/>for_removal scope]
    B --> C{ドメイン存在?}
    C -->|なし| G[バッチ終了]
    C -->|あり| D[プロジェクトコンテキスト設定]
    D --> E[ドメイン削除<br/>destroy!]
    E --> F{エラー発生?}
    F -->|あり| H[エラー記録<br/>ErrorTracking]
    F -->|なし| I[次のレコードへ]
    H --> I
    I --> C
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ドメイン検索 | pages_domains | SELECT | remove_at < 現在時刻のレコードを検索 |
| ドメイン削除 | pages_domains | DELETE | 削除対象ドメインを物理削除 |
| 関連データ削除 | pages_domain_acme_orders | DELETE | 関連するACMEオーダーを削除 |

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

#### pages_domains

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id, project_id, domain, remove_at | remove_at < Time.current | with_logging_info でproject関連も取得 |
| DELETE | - | id指定 | destroy!による物理削除 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | StandardError | 削除処理中の予期せぬエラー | ErrorTrackingに記録、次レコードへ継続 |
| - | ActiveRecord::RecordNotDestroyed | 削除制約違反 | ErrorTrackingに記録 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 個別レコード単位でのリトライなし |
| リトライ間隔 | - |
| リトライ対象エラー | 次回のバッチ実行時に再処理 |

### 障害時対応

バッチ失敗時は、次回のcron実行時に未削除のレコードが再度処理対象となります。エラーが継続する場合は、Gitlab::ErrorTrackingのログを確認して原因を特定してください。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | レコード単位 |
| コミットタイミング | 各destroy!の完了時 |
| ロールバック条件 | 各レコードの削除失敗時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 通常は少数（数件〜数十件/日） |
| 目標処理時間 | 数分以内 |
| メモリ使用量上限 | find_eachによるバッチ処理で制御 |

## 排他制御

同時実行の排他制御は行われていません（IdempotentWorkerではない）。同一ドメインが複数回処理される可能性がありますが、destroy!による冪等な削除処理のため問題ありません。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| エラーログ | 削除エラー発生時 | 例外情報（ErrorTracking経由） |
| コンテキストログ | 各ドメイン処理時 | プロジェクト情報（with_context経由） |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | 設定なし | - |
| エラー件数 | 設定なし | Sentry/ErrorTracking |

## 備考

- worker_resource_boundary: :cpu が設定されており、CPU負荷の高いワーカーとして分類されています
- data_consistency: :always により、常にプライマリデータベースを参照します
- with_logging_info スコープにより、ロギング用にプロジェクトとnamespace情報が事前読み込みされます
