# 通知設計書 11-notifyHeartbeatTimeout

## 概要

本ドキュメントは、Apache Flinkのハートビートタイムアウト通知（notifyHeartbeatTimeout）の設計仕様を記述したものである。

### 本通知の処理概要

notifyHeartbeatTimeoutは、分散システムにおけるノード間の死活監視のためのハートビート通知メカニズムの一部である。指定されたリソースIDのマシンからのハートビートが一定時間内に受信されなかった場合にリスナーにタイムアウトを通知する。

**業務上の目的・背景**：分散ストリーム処理システムにおいて、TaskManager、JobManager、ResourceManager間の接続状態を監視することは、システムの信頼性と耐障害性を確保する上で不可欠である。ハートビートが途絶えた場合、該当ノードの障害を検知し、適切なフェイルオーバー処理を開始する必要がある。

**通知の送信タイミング**：HeartbeatMonitorがスケジュールされたタイムアウト時間（heartbeatTimeoutIntervalMs）内にハートビートを受信しなかった場合、タイマースレッドから本通知が発行される。DefaultHeartbeatMonitorのrunメソッドが実行され、状態がRUNNINGからTIMEOUTに遷移する際に通知される。

**通知の受信者**：HeartbeatListenerインターフェースを実装するクラスが受信者となる。具体的には、ResourceManager、JobMaster、TaskExecutorの各コンポーネントが対象となる。

**通知内容の概要**：タイムアウトが発生したノードのResourceID（リソース識別子）が通知される。これにより受信者は、どのノードとの通信が途絶えたかを特定できる。

**期待されるアクション**：受信者は、タイムアウトしたノードとの接続を切断し、必要に応じてリソースの再割り当てやジョブの再スケジューリングを行う。TaskManagerがタイムアウトした場合はスロットの回収、JobManagerがタイムアウトした場合はジョブのフェイルオーバーが行われる。

## 通知種別

内部コールバック（Javaメソッド呼び出し）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（スケジューラスレッドから呼び出し） |
| 優先度 | 高（障害検知に直結） |
| リトライ | なし（1回限りの通知） |

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

HeartbeatManagerに登録されたHeartbeatListenerに対して通知される。リスナーは各コンポーネント（ResourceManager、JobMaster、TaskExecutor）の初期化時にHeartbeatManagerに登録される。

## 通知テンプレート

### コールバックシグネチャ

```java
void notifyHeartbeatTimeout(ResourceID resourceID);
```

### パラメータ詳細

| パラメータ名 | 型 | 説明 |
|------------|-----|------|
| resourceID | ResourceID | タイムアウトしたノードのリソース識別子 |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| resourceID | タイムアウトしたノードのID | HeartbeatMonitorが保持 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| タイマー | スケジュールタスク実行 | heartbeatTimeoutIntervalMs経過 | ScheduledExecutorがタイムアウト時間経過後にrunメソッドを実行 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 状態がRUNNING以外 | CANCELED、TIMEOUT、UNREACHABLE状態では通知されない |
| ハートビート受信 | タイムアウト前にハートビートを受信した場合、タイマーがリセットされる |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[HeartbeatMonitor初期化] --> B[タイムアウトタイマー設定]
    B --> C{ハートビート受信?}
    C -->|Yes| D[タイマーリセット]
    D --> C
    C -->|No| E[タイムアウト発生]
    E --> F{状態がRUNNING?}
    F -->|Yes| G[状態をTIMEOUTに変更]
    G --> H[notifyHeartbeatTimeout呼び出し]
    H --> I[リスナーが障害処理実行]
    F -->|No| J[処理終了]
    I --> J
```

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

### 参照テーブル一覧

データベースアクセスは発生しない（インメモリ処理）。

### 更新テーブル一覧

データベース更新は発生しない。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| リスナー例外 | notifyHeartbeatTimeout内で例外発生 | ログ出力して処理継続 |
| 状態不整合 | CAS操作失敗 | 処理をスキップ（既に別状態に遷移済み） |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

時間帯の制限なし（24時間稼働）

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

- ResourceIDは内部識別子であり、機密情報は含まれない
- 通知はJVM内部のメソッド呼び出しで完結するため、ネットワーク経由での漏洩リスクはない

## 備考

- ハートビートタイムアウト間隔はHeartbeatManagerOptions.HEARTBEAT_TIMEOUTで設定可能
- デフォルトのタイムアウト間隔は50秒

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ResourceID.java | `flink-runtime/src/main/java/org/apache/flink/runtime/clusterframework/types/ResourceID.java` | ノード識別子の構造を理解 |

**読解のコツ**: ResourceIDはStringベースの識別子で、TaskManagerやJobManagerを一意に識別する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | HeartbeatListener.java | `flink-runtime/src/main/java/org/apache/flink/runtime/heartbeat/HeartbeatListener.java` | インターフェース定義を確認（38-44行目） |

**主要処理フロー**:
1. **行38-44**: notifyHeartbeatTimeoutメソッドのJavadoc定義
2. **行44**: void notifyHeartbeatTimeout(ResourceID resourceID) シグネチャ

#### Step 3: 実装クラスを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | DefaultHeartbeatMonitor.java | `flink-runtime/src/main/java/org/apache/flink/runtime/heartbeat/DefaultHeartbeatMonitor.java` | タイムアウト検知の実装（155-160行目） |

**主要処理フロー**:
- **行155-160**: run()メソッドでタイムアウト発生時にnotifyHeartbeatTimeoutを呼び出し
- **行119**: 状態遷移（RUNNING -> TIMEOUT）のCAS操作

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

```
ScheduledExecutor.schedule()
    │
    └─ DefaultHeartbeatMonitor.run()
           │
           ├─ state.compareAndSet(RUNNING, TIMEOUT)
           │
           └─ HeartbeatListener.notifyHeartbeatTimeout(resourceID)
                  │
                  ├─ ResourceManager (タスクマネージャ管理)
                  ├─ JobMaster (ジョブ実行管理)
                  └─ TaskExecutor (リソース管理)
```

### データフロー図

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

タイマー発火 ───▶ DefaultHeartbeatMonitor ───▶ HeartbeatListener
                       │                          │
                       └─ 状態チェック            └─ 障害処理開始
                          (RUNNING?)                  (接続切断等)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| HeartbeatListener.java | `flink-runtime/src/main/java/org/apache/flink/runtime/heartbeat/HeartbeatListener.java` | インターフェース | リスナーインターフェース定義 |
| DefaultHeartbeatMonitor.java | `flink-runtime/src/main/java/org/apache/flink/runtime/heartbeat/DefaultHeartbeatMonitor.java` | 実装クラス | タイムアウト監視とコールバック発行 |
| HeartbeatManager.java | `flink-runtime/src/main/java/org/apache/flink/runtime/heartbeat/HeartbeatManager.java` | マネージャ | ハートビート管理の中核 |
| ResourceManager.java | `flink-runtime/src/main/java/org/apache/flink/runtime/resourcemanager/ResourceManager.java` | リスナー実装 | リソース管理側の処理 |
| JobMaster.java | `flink-runtime/src/main/java/org/apache/flink/runtime/jobmaster/JobMaster.java` | リスナー実装 | ジョブ管理側の処理 |
| TaskExecutor.java | `flink-runtime/src/main/java/org/apache/flink/runtime/taskexecutor/TaskExecutor.java` | リスナー実装 | タスク実行側の処理 |
