# 通知設計書 95-MissingJob

## 概要

本ドキュメントは、CronJobコントローラのActiveListに登録されているJobが実際には存在しない場合に発行されるKubernetesイベント通知「MissingJob」の設計を記述する。

### 本通知の処理概要

CronJobのStatus.ActiveListに記録されているJobが、Kubernetes API Server上で見つからない（NotFound）場合にNormalイベントとして発行される通知である。ActiveListの整合性を維持するため、存在しないJobの参照を削除する際に記録される。

**業務上の目的・背景**：CronJobはActiveListで実行中のJobを追跡するが、Jobが外部から削除されたり、API Serverの障害により情報が不整合になる場合がある。本通知はそのような不整合を検出し、ActiveListの自動クリーンアップが行われたことを記録する。これにより、運用者はJobが予期せず消失していないか確認できる。

**通知の送信タイミング**：`syncCronJob`メソッド内で、ActiveListに含まれるJobの存在確認を行い、API Serverからも見つからない（NotFound）場合に発行される（行477-496）。

**通知の受信者**：Kubernetesイベントとして該当CronJobオブジェクトに記録される。

**通知内容の概要**：EventTypeはNormal、Reasonは「MissingJob」、メッセージにはActiveListにあるが見つからなかったJob名が含まれる。フォーマットは「Active job went missing: {Job名}」である。

**期待されるアクション**：受信者はJobが意図的に削除されたのか、予期せず消失したのかを確認する。意図しない消失の場合は、API Serverの障害やetcdの問題を調査する必要がある。

## 通知種別

Kubernetesイベント（Event API リソース）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（syncCronJob処理内で即座に発行） |
| 優先度 | 中（Jobの予期せぬ消失の可能性） |
| リトライ | N/A（検出時に一度だけ発行） |

### 送信先決定ロジック

CronJobコントローラの`recorder.Eventf`メソッドにより、対象のCronJobオブジェクトに対してイベントが記録される。

## 通知テンプレート

### メール通知の場合

本通知はKubernetesイベントであり、メール送信は行わない。

| 項目 | 内容 |
|-----|------|
| 送信元アドレス | N/A（Kubernetesイベント） |
| 送信元名称 | cronjob-controller |
| 件名 | N/A |
| 形式 | Kubernetesイベントリソース |

### 本文テンプレート

```
Active job went missing: %v
```

変数`%v`にはActiveListに記録されているが見つからなかったJob名（`j.Name`）が挿入される。

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | N/A | N/A | 添付ファイルなし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| j.Name | 消失したJob名 | CronJob.Status.Active[].Name | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| コントローラ同期 | CronJob同期処理 | ActiveListのJobがInformerキャッシュにもAPI Serverにも存在しない（NotFound）場合 | syncCronJob内のActiveList整合性チェック |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| Jobが存在する | InformerキャッシュまたはAPI Serverで見つかった場合 |
| API Serverエラー | NotFound以外のエラーの場合はイベント発行せずerror返却 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[syncCronJob ActiveListチェック] --> B[各ActiveJob走査]
    B --> C{childrenJobsマップに存在?}
    C -->|存在する| D[スキップ]
    C -->|存在しない| E[API ServerにGetリクエスト]
    E --> F{API Server応答}
    F -->|NotFound| G[MissingJobイベント発行]
    G --> H[ActiveListから削除]
    H --> I[updateStatus=true]
    F -->|その他エラー| J[error返却]
    F -->|Job存在| K[スキップ（キャッシュ遅延）]
    D --> L[次のJobへ]
    I --> L
    J --> L
    K --> L
```

## データベース参照・更新仕様

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| CronJob | ActiveList取得 | Informerキャッシュ経由 |
| Job | 存在確認 | Informerキャッシュ + API Server直接アクセス |

### テーブル別参照項目詳細

#### CronJob

| 参照項目（カラム名） | 用途 | 取得条件 |
|-------------------|------|---------|
| Status.Active | ActiveListのJob参照一覧 | syncCronJob内 |
| Status.Active[].UID | Jobの一意識別子 | 各ActiveJob |
| Status.Active[].Namespace | JobのNamespace | 各ActiveJob |
| Status.Active[].Name | JobのName | 各ActiveJob |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| CronJob | UPDATE | Status.Active（消失JobをActiveListから削除） |
| Event | INSERT | MissingJobイベント作成 |

#### 送信ログテーブル

| 操作 | 項目（カラム名） | 更新値 | 備考 |
|-----|-----------------|-------|------|
| INSERT | Event.Type | Normal | イベント種別 |
| INSERT | Event.Reason | MissingJob | イベント理由 |
| INSERT | Event.Message | Active job went missing: {j.Name} | 消失Job名 |
| INSERT | Event.Source.Component | cronjob-controller | 発行元コンポーネント |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| API Serverエラー（NotFound以外） | API ServerへのGetリクエストが失敗 | error返却、ワークキューで再試行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | N/A（MissingJobイベント自体はリトライ不要） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | Kubernetesイベントのデフォルト集約ルールに従う |
| 1日あたり上限 | 特に制限なし |

### 配信時間帯

制限なし。

## セキュリティ考慮事項

消失したJob名がメッセージに含まれるが、機密情報は含まれない。

## 備考

- Informerキャッシュに存在しないJobについて、API Serverに直接Getリクエストを行う二段階チェックを実装している（行484）。これはSlow Watchによるキャッシュ遅延への対策である。
- MissingJob検出後はdeleteFromActiveListで参照を削除し、次回のスケジュールでJobが新規作成される。

---

## コードリーディングガイド

本通知を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.go | `staging/src/k8s.io/api/core/v1/types.go` | ObjectReference型（CronJob.Status.Active要素の型）のNamespace、Name、UIDフィールドを理解する |

**読解のコツ**: CronJob.Status.ActiveはObjectReference配列であり、各要素はJobへの参照を保持する。

#### Step 2: ActiveList整合性チェックを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cronjob_controllerv2.go | `pkg/controller/cronjob/cronjob_controllerv2.go` | syncCronJob内のActiveListチェック（行477-496）を理解する |

**主要処理フロー**:
1. **行477**: ActiveList走査ループ開始
2. **行478-480**: childrenJobsマップで存在チェック（Informerキャッシュ）
3. **行484**: API ServerにGetリクエスト（キャッシュ遅延対策）
4. **行486-491**: NotFound -> MissingJobイベント発行 + ActiveListから削除
5. **行489**: recorder.Eventf "MissingJob"
6. **行490**: deleteFromActiveList
7. **行492-493**: その他エラー -> error返却

#### Step 3: childrenJobsマップの構築を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cronjob_controllerv2.go | `pkg/controller/cronjob/cronjob_controllerv2.go` | syncCronJob冒頭（行434-472）でchildrenJobsマップがどのように構築されるかを理解する |

### プログラム呼び出し階層図

```
ControllerV2.syncCronJob (行426)
    |
    +-- [childrenJobsマップ構築] (行434-472)
    |
    +-- [ActiveList整合性チェック] (行477-496)
         |
         +-- childrenJobs[j.UID] 存在チェック (行478)
         +-- jobControl.GetJob (行484) -- キャッシュに無い場合
         |
         +-- [NotFound] (行486)
         |    |
         |    +-- recorder.Eventf "MissingJob" (行489) ★本通知
         |    +-- deleteFromActiveList (行490)
         |
         +-- [その他エラー] (行492)
              +-- error返却
```

### データフロー図

```
[入力]                           [処理]                         [出力]

CronJob.Status.Active      --> syncCronJob                  --> MissingJob Event
  (ActiveList)                   |                               (Normal)
Job Informerキャッシュ            +-- childrenJobsマップ照合
API Server (Job Get)             +-- jobControl.GetJob
                                 +-- recorder.Eventf
                                 +-- deleteFromActiveList
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cronjob_controllerv2.go | `pkg/controller/cronjob/cronjob_controllerv2.go` | ソース | MissingJobイベント発行（行489）、ActiveList整合性チェック（行477-496） |
| utils.go | `pkg/controller/cronjob/utils.go` | ソース | deleteFromActiveList関数（行79-92） |
| injection.go | `pkg/controller/cronjob/injection.go` | ソース | jobControl.GetJob（行99-101） |
