# バッチ設計書 84-Namespaces::EnableDescendantsCacheCronWorker

## 概要

本ドキュメントは、名前空間の子孫キャッシュを有効化するバッチ処理「Namespaces::EnableDescendantsCacheCronWorker」の設計仕様を定義するものである。

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

このバッチは、大規模な名前空間（700件以上の子孫を持つグループ）を特定し、それらのキャッシュを有効化するためのレコードをNamespaces::Descendantsテーブルに登録するCronジョブである。

**業務上の目的・背景**：GitLabでは、大規模なグループ（多数のサブグループやプロジェクトを持つ）に対するクエリパフォーマンスを向上させるために、子孫情報のキャッシュを使用する。このバッチは、キャッシュ対象となる大規模グループを自動的に識別し、キャッシュの有効化をスケジュールする。GitLab.comの上位3000名前空間をカバーするため、閾値は700件に設定されている。

**バッチの実行タイミング**：Cronジョブとして定期的に実行される。最大実行時間は45秒に制限されている。

**主要な処理内容**：
1. 前回処理した最後のグループIDをRedisから取得（カーソル位置）
2. グループをバッチ（5000件ずつ）で取得
3. 各グループの子孫数をカウント（500件ずつ）
4. 閾値（700件）以上の子孫を持つグループをキャッシュ対象としてマーク
5. Namespaces::Descendantsテーブルにupsert
6. カーソル位置をRedisに保存（1日有効）

**前後の処理との関連**：ProcessOutdatedNamespaceDescendantsCronWorker（No.85）と連携して動作する。本バッチがキャッシュ対象を特定し、No.85が実際のキャッシュ更新を行う。

**影響範囲**：Namespaces::Descendantsテーブル、Redisのカーソル位置キー。

## バッチ種別

データ収集・キャッシュ有効化処理

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 定期実行（Cron） |
| 実行時刻 | 設定により異なる |
| 実行曜日 | 毎日 |
| 実行日 | 毎日 |
| トリガー | cron |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Redis接続 | SharedStateのRedisに接続可能であること |
| feature_category | groups_and_projects機能が有効であること |

### 実行可否判定

特別な実行可否判定なし。45秒の最大実行時間制限あり。

## 入力仕様

### 入力パラメータ

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

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| Group | DB | グループテーブル |
| Namespace | DB | 名前空間テーブル（子孫カウント用） |
| Redis | Cache | カーソル位置（last_id） |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| namespaces_descendants | DB | キャッシュ対象のグループID |
| Redis | Cache | 次回処理開始位置 |
| Sidekiqログ | Metadata | over_time, last_id, cache_count |

### 出力ファイル仕様

ファイル出力なし。

## 処理フロー

### 処理シーケンス

```
1. ワーカー起動
   └─ Sidekiqによりジョブがキューから取得される
2. 実行時間リミッター初期化
   └─ RuntimeLimiterを45秒で初期化
3. カーソル位置取得
   └─ Redisから前回の最後のグループIDを取得
4. グループバッチ処理
   ├─ GROUP_BATCH_SIZE(5000)ずつグループを取得
   ├─ 各グループの子孫数をカウント
   ├─ CACHE_THRESHOLD(700)以上ならキャッシュ対象に追加
   └─ 時間超過または全グループ処理完了まで繰り返し
5. キャッシュ対象の永続化
   └─ PERSIST_SLICE_SIZE(100)ずつupsert
6. カーソル位置保存
   └─ Redisに次回開始位置を保存（1日有効）
7. 処理完了
   └─ メタデータログ出力
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[RuntimeLimiter初期化 45秒]
    B --> C[Redisからカーソル取得]
    C --> D[グループバッチ取得 5000件]
    D --> E{グループ存在?}
    E -->|なし| F[カーソルリセット]
    E -->|あり| G[子孫数カウント 500件ずつ]
    G --> H{子孫数 >= 700?}
    H -->|Yes| I[キャッシュ対象に追加]
    H -->|No| J{時間超過?}
    I --> J
    J -->|No| K{次のグループ?}
    K -->|あり| G
    K -->|なし| D
    J -->|Yes| L[キャッシュ対象を永続化]
    L --> M[カーソル位置保存]
    F --> N[メタデータログ出力]
    M --> N
    N --> O[バッチ終了]
```

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

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

| 処理 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| グループ取得 | groups | SELECT | バッチでグループを取得 |
| 子孫カウント | namespaces | SELECT | 各グループの子孫数をカウント |
| キャッシュ登録 | namespaces_descendants | UPSERT | キャッシュ対象グループを登録 |

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

#### groups

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | id | id > last_id | each_batchで5000件ずつ |

#### namespaces_descendants

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPSERT | namespace_id, outdated_at | namespace_id, Time.current | 100件ずつupsert |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | 時間超過 | 45秒経過 | 処理中断、次回継続 |
| - | DBエラー | データベース接続失敗 | 自動リトライ |
| - | Redisエラー | Redis接続失敗 | 自動リトライ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | Sidekiqデフォルト |
| リトライ間隔 | Sidekiqデフォルト（指数バックオフ） |
| リトライ対象エラー | 一般的な例外 |

### 障害時対応

idempotent!が設定されているため、再実行しても安全。カーソル位置がRedisに保存されているため、中断後も継続処理可能。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | upsertバッチ単位（100件） |
| コミットタイミング | 各upsertバッチ後 |
| ロールバック条件 | upsert失敗時 |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 可変（グループ数に依存） |
| 目標処理時間 | 最大45秒（MAX_RUNTIME） |
| メモリ使用量上限 | バッチ処理により制限 |

## 排他制御

特別な排他制御なし。カーソルによる増分処理で複数実行時の競合を軽減。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| 完了ログ | バッチ終了時 | over_time, last_id, cache_count |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| 処理時間 | 45秒（MAX_RUNTIME） | 運用チーム |
| 連続失敗回数 | 3回以上 | 運用チーム |

## 備考

- feature_category: :groups_and_projects
- data_consistency: :sticky
- idempotent: true
- MAX_RUNTIME: 45秒
- GROUP_BATCH_SIZE: 5000
- NAMESPACE_BATCH_SIZE: 500
- PERSIST_SLICE_SIZE: 100
- CACHE_THRESHOLD: 700（GitLab.comの上位3000名前空間をカバー）
- CURSOR_KEY: 'enable_namespace_descendants_cron_worker'
- カーソルの有効期限: 1日
