# 機能設計書 129-ゲートウェイ

## 概要

本ドキュメントは、OpenSearchにおけるクラスタ状態の永続化・復元を行うゲートウェイ機能の設計を記載する。

### 本機能の処理概要

本機能は、クラスタの初期起動時にクラスタ状態（メタデータ、インデックス情報）を復元し、ノード間のシャード割り当てを管理するゲートウェイ機能である。

**業務上の目的・背景**：クラスタが再起動した場合、永続化されたクラスタ状態を復元して正常な運用状態に戻す必要がある。ゲートウェイ機能は、クラスタマネージャ選出後のクラスタ状態復元、必要なデータノード数の待機、シャードの初期割り当てなどを統合的に管理する。

**機能の利用シーン**：クラスタの初回起動、クラスタ全体の再起動、クラスタマネージャ障害からの復旧、Danglingインデックスの検出・復元時に利用される。

**主要な処理内容**：
1. GatewayServiceによるクラスタ状態復元タイミングの制御
2. Gateway.performStateRecovery()でのメタデータ復元
3. GatewayAllocator / ShardsBatchGatewayAllocatorによるシャード割り当て
4. PersistedClusterStateServiceによるクラスタ状態の永続化
5. DanglingIndicesStateによるDanglingインデックスの管理

**関連システム・外部連携**：AllocationServiceによるシャード再配置。リモートストア有効時はremoteパッケージのリモートゲートウェイ機能と連携。

**権限による制御**：クラスタマネージャノードでのみ状態復元が実行される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 128 | Danglingインデックス一覧 | 主機能 | すべてのDanglingインデックスを返す処理 |
| 129 | Danglingインデックスインポート | 主機能 | 指定したDanglingインデックスをインポートする処理 |
| 130 | Danglingインデックス削除 | 関連 | 指定したDanglingインデックスを削除する処理 |

## 機能種別

基盤機能（クラスタ状態管理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| gateway.expected_data_nodes | int | No | 期待されるデータノード数（デフォルト: -1） | -1以上 |
| gateway.recover_after_time | TimeValue | No | 状態復元までの待機時間 | 正の値 |
| gateway.recover_after_data_nodes | int | No | 最低データノード数（デフォルト: -1） | -1以上 |

### 入力データソース

ノードの永続化されたクラスタ状態、クラスタマネージャノードのメタデータ

## 出力仕様

### 出力データ

本機能の出力はクラスタ状態の復元である。

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ClusterState | Object | 復元されたクラスタ状態（メタデータ、ルーティングテーブル等） |

### 出力先

クラスタ状態（インメモリ）

## 処理フロー

### 処理シーケンス

```
1. GatewayService起動
   └─ クラスタマネージャノードの場合のみClusterStateListenerとして登録
2. クラスタ状態変更イベント受信
   └─ ローカルノードがクラスタマネージャか確認
   └─ STATE_NOT_RECOVERED_BLOCKの存在を確認
3. データノード数チェック
   └─ recover_after_data_nodesの条件確認
   └─ expected_data_nodesとの比較
4. 状態復元実行
   └─ Coordinatorの場合: RecoverStateUpdateTask
   └─ それ以外: Gateway.performStateRecovery()
5. 復元完了
   └─ STATE_NOT_RECOVERED_BLOCKの解除
   └─ ルーティングテーブル更新
   └─ AllocationService.reroute()
```

### フローチャート

```mermaid
flowchart TD
    A[クラスタ状態変更] --> B{ローカルノードがCM?}
    B -->|No| C[処理なし]
    B -->|Yes| D{STATE_NOT_RECOVERED_BLOCK?}
    D -->|なし| E[既に復元済み]
    D -->|あり| F{データノード数十分?}
    F -->|No| G[待機]
    F -->|Yes| H{expected_data_nodes未達?}
    H -->|Yes| I{recover_after_time設定?}
    I -->|Yes| J[遅延後に復元実行]
    I -->|No| K[即時復元実行]
    H -->|No| K
    J --> L[RecoverStateUpdateTask]
    K --> L
    L --> M[STATE_NOT_RECOVERED_BLOCK解除]
    M --> N[AllocationService.reroute]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | クラスタマネージャ限定 | 状態復元はクラスタマネージャノードでのみ実行 | 常時 |
| BR-002 | 一度きりの復元 | STATE_NOT_RECOVERED_BLOCKが存在する場合のみ復元を試行 | 起動時 |
| BR-003 | デフォルト待機時間 | expected_data_nodes設定時はデフォルトで5分間待機 | expected_data_nodes >= 0 |
| BR-004 | メタデータバージョン選択 | 複数ノードのメタデータから最新バージョンを選出 | 復元時 |
| BR-005 | requiredAllocation | 最低1ノードからのメタデータ取得が必要 | 復元時 |

### 計算ロジック

- メタデータ選出: 全クラスタマネージャノードから取得したメタデータのうち、最大versionを持つものを選出
- インデックスメタデータ: 各ノードのインデックスメタデータを比較し、最大versionのものを選出

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 状態復元 | クラスタ状態ファイル | SELECT | 永続化されたクラスタ状態の読み出し |
| 状態永続化 | クラスタ状態ファイル | UPDATE | クラスタ状態のファイルへの書き出し |

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

PersistedClusterStateServiceにより、Luceneインデックス形式でクラスタ状態がディスクに永続化される。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| GatewayException | ゲートウェイ例外 | 状態復元処理中の致命的エラー | ログ確認、ノード再起動 |
| FailedNodeException | ノード障害 | メタデータ取得先ノードへの通信失敗 | 警告ログ出力、利用可能ノードで続行 |

### リトライ仕様

状態復元失敗時はrecoveryInProgressとscheduledRecoveryフラグをリセットし、次回のクラスタ状態変更時に再試行可能。

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

ClusterStateUpdateTaskとしてアトミックに処理される。

## パフォーマンス要件

GENERICスレッドプールで実行。大規模クラスタではメタデータ取得に時間を要する場合がある。

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

STATE_NOT_RECOVERED_BLOCKが設定されている間、全てのClusterBlockLevelでクラスタへのアクセスがブロックされる。

## 備考

リモートストア有効時は、remoteパッケージ内のRemoteClusterStateServiceがリモートストアからのクラスタ状態復元を担当する。

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | GatewayMetaState.java | `server/src/main/java/org/opensearch/gateway/GatewayMetaState.java` | 永続化されたクラスタ状態のメタデータ管理 |
| 1-2 | MetadataStateFormat.java | `server/src/main/java/org/opensearch/gateway/MetadataStateFormat.java` | メタデータのシリアライズ形式 |

#### Step 2: GatewayServiceを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | GatewayService.java | `server/src/main/java/org/opensearch/gateway/GatewayService.java` | クラスタ状態復元のタイミング制御 |

**主要処理フロー**:
- **71-97行目**: 設定定義（expected_data_nodes, recover_after_time, recover_after_data_nodes, STATE_NOT_RECOVERED_BLOCK）
- **140-145行目**: recoveryRunnable - Coordinator使用時はRecoverStateUpdateTask、それ以外はGateway.performStateRecovery()
- **164-208行目**: clusterChanged()でクラスタ状態変更時の復元判定ロジック
- **210-247行目**: performStateRecovery()で遅延実行または即時実行の分岐
- **254-268行目**: RecoverStateUpdateTask.execute()でルーティングテーブル更新とブロック解除

#### Step 3: Gateway本体を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Gateway.java | `server/src/main/java/org/opensearch/gateway/Gateway.java` | メタデータの復元ロジック |

**主要処理フロー**:
- **72-145行目**: performStateRecovery()で全クラスタマネージャノードからメタデータを収集し、最新バージョンを選出
- **86-101行目**: 各ノードのメタデータからグローバル状態を選出
- **110-139行目**: インデックスメタデータの選出

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

```
GatewayService (ClusterStateListener)
    |
    +-- clusterChanged()
    |       +-- 復元タイミング判定
    |
    +-- performStateRecovery()
    |       +-- RecoverStateUpdateTask (Coordinator利用時)
    |       |       +-- ClusterStateUpdaters.updateRoutingTable()
    |       |       +-- ClusterStateUpdaters.removeStateNotRecoveredBlock()
    |       |       +-- AllocationService.reroute()
    |       |
    |       +-- Gateway.performStateRecovery() (非Coordinator時)
    |               +-- TransportNodesListGatewayMetaState.list()
    |               +-- メタデータバージョン比較・選出
    |               +-- ClusterStateUpdaters処理
    |
    +-- GatewayAllocator / ShardsBatchGatewayAllocator
            +-- PrimaryShardAllocator
            +-- ReplicaShardAllocator
```

### データフロー図

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

クラスタ状態変更  -->  GatewayService            -->  復元判定
ノードメタデータ  -->  Gateway.performStateRecovery() --> ClusterState
永続化状態      -->  PersistedClusterStateService --> メタデータ読み出し
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| GatewayService.java | `server/src/main/java/org/opensearch/gateway/` | ソース | 復元タイミング制御 |
| Gateway.java | 同上 | ソース | メタデータ復元ロジック |
| GatewayMetaState.java | 同上 | ソース | 永続化メタデータ管理 |
| GatewayAllocator.java | 同上 | ソース | シャードアロケーション |
| ShardsBatchGatewayAllocator.java | 同上 | ソース | バッチシャードアロケーション |
| PrimaryShardAllocator.java | 同上 | ソース | プライマリシャード割り当て |
| ReplicaShardAllocator.java | 同上 | ソース | レプリカシャード割り当て |
| PersistedClusterStateService.java | 同上 | ソース | クラスタ状態永続化 |
| DanglingIndicesState.java | 同上 | ソース | Danglingインデックス管理 |
| ClusterStateUpdaters.java | 同上 | ソース | クラスタ状態更新ユーティリティ |
| GatewayModule.java | 同上 | ソース | DIモジュール |
| MetaStateService.java | 同上 | ソース | メタ状態サービス |
| IncrementalClusterStateWriter.java | 同上 | ソース | インクリメンタル書き込み |
