# 通知設計書 26-notifyTimeout

## 概要

本ドキュメントは、Apache Flink のタイムアウト通知（notifyTimeout）の詳細設計を記載したものである。`TimerService` によるタイムアウトイベントが発生した際に、リスナーに通知する仕組みを定義する。

### 本通知の処理概要

**業務上の目的・背景**：分散システムにおいて、タイムアウト処理は非常に重要な役割を果たす。スロット割り当てのタイムアウト、ハートビートのタイムアウト、その他時間制限のある操作において、指定時間内に応答がない場合に適切なアクションを実行する必要がある。本通知は、時間ベースのイベント管理を抽象化し、コンポーネントがタイムアウトに対応できるようにする汎用的な通信メカニズムである。

**通知の送信タイミング**：`DefaultTimerService` 内で、登録されたタイムアウトの指定時間が経過した際に発生する。`ScheduledExecutorService` によってスケジュールされたタスクが実行され、`Timeout.run()` メソッドから `notifyTimeout()` が呼び出される。

**通知の受信者**：`TimeoutListener<K>` インターフェースを実装するコンポーネントが受信者となる。代表的な実装として `TaskSlotTableImpl` があり、スロットのタイムアウト管理に使用される。

**通知内容の概要**：通知には、タイムアウトしたイベントを識別するキーと、タイムアウトチケット（UUID）が含まれる。チケットはタイムアウトの有効性を検証するために使用され、古いタイムアウトを無視するのに役立つ。

**期待されるアクション**：リスナーは、キーとチケットを使用してタイムアウトの有効性を確認し、有効な場合は対応するアクション（スロット解放、リソースクリーンアップ等）を実行する。

## 通知種別

内部コールバック通知（Java インターフェースコールバック）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（Scheduled Task 内） |
| 優先度 | 中 |
| リトライ | なし |

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

`DefaultTimerService.start()` で登録された `TimeoutListener<K>` に対して通知が送信される。タイムアウトは `registerTimeout()` メソッドでキー、遅延時間、時間単位を指定して登録され、指定時間後に自動的に通知される。

## 通知テンプレート

### コールバック通知の場合

| 項目 | 内容 |
|-----|------|
| インターフェース | `TimeoutListener<K>` |
| メソッド | `notifyTimeout` |
| 形式 | Java インターフェースコールバック |

### パラメータ

```java
void notifyTimeout(K key, UUID ticket);
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| key | タイムアウトイベントのキー | 登録時のパラメータ | Yes |
| ticket | タイムアウトチケット（UUID） | 登録時に自動生成 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| タイムアウト | `Timeout.run()` 実行 | 登録済みタイムアウト | 指定時間経過後に自動実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| キャンセル済み | `unregisterTimeout()` で登録解除済み |
| サービス停止 | TimerService が停止済み |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[registerTimeout 呼び出し] --> B[既存タイムアウトのキャンセル]
    B --> C[新規 Timeout オブジェクト作成]
    C --> D[UUID チケット生成]
    D --> E[ScheduledExecutorService にスケジュール]
    E --> F{指定時間経過?}
    F -->|No| G[待機中]
    F -->|Yes| H[Timeout.run 実行]
    H --> I[timeoutListener.notifyTimeout]
    I --> J{チケット有効?}
    J -->|No| K[処理スキップ]
    J -->|Yes| L[タイムアウト処理実行]
    L --> M[終了]
    K --> M
    G --> F
```

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

### 参照テーブル一覧

該当なし（インメモリ管理）

### メモリ内データ構造

| データ構造 | クラス | 用途 | 備考 |
|-----------|------|------|------|
| timeouts | `Map<K, Timeout<K>>` | タイムアウト管理 | DefaultTimerService |
| scheduledTimeout | `ScheduledFuture<?>` | スケジュールタスク | Timeout 内部 |
| ticket | `UUID` | タイムアウト識別 | Timeout 内部 |

### 更新データ一覧

| データ構造 | 操作 | 概要 |
|-----------|------|------|
| timeouts | PUT | 新規タイムアウト登録 |
| timeouts | REMOVE | タイムアウト解除 |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| リスナー未登録 | サービス未開始 | IllegalStateException |
| 無効なチケット | 登録後に再登録 | リスナー側でスキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | なし |
| リトライ対象エラー | なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 制限なし |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし（システム稼働中常時）

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

- タイムアウトチケット（UUID）により、古いタイムアウトと新しいタイムアウトを区別できる
- 不正なチケットによる誤動作を防ぐため、`isValid()` メソッドで検証が可能

## 備考

- ジェネリック型 `<K>` により、任意のキー型でタイムアウトを管理可能
- 同一キーで再登録すると、既存のタイムアウトがキャンセルされる
- スロット管理における典型的な使用例は `TaskSlotTableImpl`

---

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

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

### 推奨読解順序

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

タイムアウト管理に使用されるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | TimeoutListener.java | `flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/` | リスナーインターフェース |
| 1-2 | TimerService.java | `flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/` | タイマーサービスインターフェース |

**読解のコツ**: `TimeoutListener<K>` はジェネリック型で、キーの型を柔軟に定義可能。

#### Step 2: エントリーポイントを理解する

リスナーインターフェースと通知の起点を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TimeoutListener.java | `flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/` | リスナーインターフェース定義 |

**主要処理フロー**:
- **行 30-37**: `notifyTimeout()` メソッドシグネチャ
- パラメータは `key` と `ticket`（UUID）の2つ

#### Step 3: 通知送信ロジックを理解する

DefaultTimerService でのタイムアウト管理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DefaultTimerService.java | `flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/` | タイマーサービス実装 |

**主要処理フロー**:
1. **行 66-72**: `start()` - サービス開始とリスナー登録
2. **行 85-96**: `registerTimeout()` - タイムアウト登録
3. **行 90-92**: 既存タイムアウトの解除
4. **行 94-95**: 新規 Timeout 作成とマップ登録
5. **行 136-170**: `Timeout` 内部クラス
6. **行 166-168**: `run()` メソッド - `notifyTimeout()` 呼び出し

#### Step 4: 受信側の処理を理解する

TaskSlotTableImpl での通知受信処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | TaskSlotTableImpl.java | `flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/` | タスクスロットテーブル実装 |

**主要処理フロー**:
- スロットのタイムアウト処理で `TimeoutListener<AllocationID>` として使用
- `isValid()` でチケットの有効性を検証

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

```
外部呼び出し（スロット割り当て等）
    │
    ├─ DefaultTimerService.registerTimeout(key, delay, unit)  [行 85-96]
    │      │
    │      ├─ unregisterTimeout(key)  [既存キャンセル, 行 90-92]
    │      └─ new Timeout(...)  [行 94-95]
    │              │
    │              ├─ scheduledExecutorService.schedule()  [行 154]
    │              └─ ticket = UUID.randomUUID()  [行 155]
    │
    └─ [指定時間経過後]
            └─ Timeout.run()  [行 166-168]
                    └─ timeoutListener.notifyTimeout(key, ticket)
                            │
                            └─ TaskSlotTableImpl（等）
                                    └─ isValid(key, ticket) でチケット検証  [行 116-124]
```

### データフロー図

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

registerTimeout       ───▶  DefaultTimerService        ───▶  コールバック通知
(key, delay, unit)           (スケジューリング)              (TimeoutListener へ)
      │                              │                            │
      │                              ▼                            ▼
      │               ScheduledExecutorService          notifyTimeout(key, ticket)
      │               (遅延実行)                         (タイムアウト処理)
      │                              │                            │
      │                              ▼                            ▼
      │               Timeout.run()                      isValid(key, ticket)
      │               (実行時刻到達)                      (チケット検証)
      │                              │
      └──────────────────────────────┘
              タイムアウト情報
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| TimeoutListener.java | `flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/` | ソース | リスナーインターフェース |
| TimerService.java | `flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/` | ソース | タイマーサービスインターフェース |
| DefaultTimerService.java | `flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/` | ソース | タイマーサービス実装 |
| TaskSlotTableImpl.java | `flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/slot/` | ソース | タスクスロットテーブル（使用例） |
