# 機能設計書 120-リカバリ

## 概要

本ドキュメントは、OpenSearchのリカバリ（Recovery）機能の設計書である。シャードリカバリの状態確認・管理機能を提供する。

### 本機能の処理概要

**業務上の目的・背景**：OpenSearchではノード障害、シャード再配置、レプリカ作成、スナップショットリストアなどの場面でシャードリカバリが発生する。リカバリAPIは、進行中および完了済みのリカバリ操作の詳細な状態情報を提供し、運用者がリカバリの進捗を監視・管理できるようにする。

**機能の利用シーン**：ノード障害後のリカバリ進捗監視、シャード再配置の状態確認、レプリカ追加時の同期状態確認、クラスタメンテナンス時の状態監視などの場面で利用される。

**主要な処理内容**：
1. RESTリクエストの受付と対象インデックスの解決
2. クラスタブロックチェック（METADATA_READ）
3. 全シャード（リロケーションターゲット含む）からRecoveryStateを収集
4. activeOnly=trueの場合、完了済みリカバリを除外
5. インデックス名ごとにRecoveryStateをグループ化して返却

**関連システム・外部連携**：シャードアロケーション、スナップショットリストア、セグメントレプリケーションと連携する。

**権限による制御**：METADATA_READレベルのクラスタブロックチェック。対象インデックスへの読み取り権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 84 | リカバリ情報 | 主画面 | 進行中のインデックスシャードリカバリ情報を返す処理 |

## 機能種別

監視 / 状態確認

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| index | String | No | 対象インデックス名（カンマ区切り、未指定時は全インデックス） | 有効なインデックス名 |
| detailed | boolean | No | 詳細情報の表示（物理ファイルリスト等、デフォルト: false） | true/false |
| active_only | boolean | No | 進行中のリカバリのみ表示（デフォルト: false） | true/false |

### 入力データソース

REST API経由のリクエスト。`GET /{index}/_recovery` または `GET /_recovery`。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| {index_name} | Array[RecoveryState] | インデックス名ごとのリカバリ状態リスト |
| RecoveryState.stage | String | リカバリステージ（INIT, INDEX, VERIFY_INDEX, TRANSLOG, FINALIZE, DONE） |
| RecoveryState.type | String | リカバリタイプ（STORE, SNAPSHOT, REPLICA, RELOCATING等） |
| RecoveryState.shardId | Object | 対象シャードID |
| RecoveryState.source | Object | リカバリソース情報 |
| RecoveryState.target | Object | リカバリターゲット情報 |

### 出力先

REST APIレスポンス（JSON形式）

## 処理フロー

### 処理シーケンス

```
1. RESTリクエスト受付
   └─ パラメータ解析、RecoveryRequest生成
2. クラスタブロックチェック
   └─ METADATA_READレベルのグローバル・インデックスブロック確認
3. シャード特定
   └─ allShardsIncludingRelocationTargetsで全シャード（リロケーション含む）を取得
4. 各シャードでRecoveryState取得
   └─ IndexShard.recoveryState()でRecoveryStateを取得
5. 結果フィルタリング
   └─ activeOnly=trueの場合、stage != DONEのみを残す
6. インデックス別グルーピング
   └─ インデックス名をキーとしてRecoveryStateをマップ化
7. レスポンス返却
   └─ RecoveryResponseとして返却
```

### フローチャート

```mermaid
flowchart TD
    A[RESTリクエスト受信] --> B[RecoveryRequest生成]
    B --> C{クラスタブロックチェック}
    C -->|ブロックあり| D[例外返却]
    C -->|OK| E[全シャード取得<br/>リロケーション含む]
    E --> F[各シャードのRecoveryState取得]
    F --> G{RecoveryState != null?}
    G -->|Yes| H{activeOnly?}
    G -->|No| I[スキップ]
    H -->|Yes & stage != DONE| J[結果に追加]
    H -->|No| J
    H -->|Yes & stage == DONE| I
    J --> K[インデックス別にグループ化]
    K --> L[RecoveryResponse返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-120-01 | activeOnlyフィルタ | activeOnly=trueの場合、Stage.DONEのリカバリは除外される | activeOnly設定時 |
| BR-120-02 | リロケーション含む | リロケーションターゲットシャードも取得対象に含まれる | 常時 |
| BR-120-03 | nullスキップ | RecoveryStateがnullのシャードはスキップされる | RecoveryState取得時 |
| BR-120-04 | IndicesOptions | STRICT_EXPAND_OPEN_CLOSEDでオープン・クローズ両方のインデックスを対象 | デフォルト |

### 計算ロジック

特になし。各シャードのRecoveryStateを読み取って返却する。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リカバリ状態取得 | 対象インデックス | SELECT | 各シャードのRecoveryStateの読み取り |

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

読み取り専用操作。データの変更は行わない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | ClusterBlockException | METADATA_READブロック | ブロックを解除する |
| 404 | IndexNotFoundException | 指定インデックスが存在しない | インデックス名を確認する |

### リトライ仕様

個別シャードの失敗はshardFailuresに記録され、他のシャードの処理は続行される。

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

読み取り専用操作のため、トランザクション管理は不要。

## パフォーマンス要件

- MANAGEMENTスレッドプールで実行される
- detailed=trueの場合、物理ファイルリスト等の追加情報取得により応答が遅くなる可能性がある

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

- METADATA_READレベルの権限チェック
- 対象インデックスへの読み取りアクセス権限

## 備考

- アクション名: indices:monitor/recovery
- スレッドプール: MANAGEMENT
- TransportBroadcastByNodeActionを拡張
- IndicesOptions: STRICT_EXPAND_OPEN_CLOSED

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | RecoveryRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/recovery/RecoveryRequest.java` | リクエストパラメータ：detailed, activeOnly |
| 1-2 | RecoveryState.java | `server/src/main/java/org/opensearch/indices/recovery/RecoveryState.java` | リカバリ状態データ構造：Stage、Type等 |

**読解のコツ**: RecoveryRequestはBroadcastRequestを拡張。detailedとactiveOnlyの2つのbooleanフラグのみで非常にシンプル。IndicesOptions.STRICT_EXPAND_OPEN_CLOSEDがデフォルト（74行目）。

**主要処理フロー**:
- **52-53行目**: デフォルト値。detailed=false, activeOnly=false
- **73-75行目**: コンストラクタ。STRICT_EXPAND_OPEN_CLOSED IndicesOptions

#### Step 2: トランスポートアクションを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TransportRecoveryAction.java | `server/src/main/java/org/opensearch/action/admin/indices/recovery/TransportRecoveryAction.java` | ブロードキャスト操作のメインロジック |

**主要処理フロー**:
- **66行目**: TransportBroadcastByNodeActionを拡張。RecoveryStateをシャード結果として使用
- **85行目**: MANAGEMENTスレッドプールで実行
- **96-123行目**: newResponse。RecoveryStateをインデックス名でグループ化、activeOnlyフィルタリング
- **114-116行目**: activeOnly判定。stage != DONE のみ追加
- **131-134行目**: shardOperation。IndexShard.recoveryState()でRecoveryStateを取得
- **138-139行目**: shards()。allShardsIncludingRelocationTargetsで全シャード取得
- **143-144行目**: checkGlobalBlock。METADATA_READブロック確認

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

```
REST: GET /{index}/_recovery
    |
    +-- RestRecoveryAction
            |
            +-- TransportRecoveryAction (TransportBroadcastByNodeAction)
                    |
                    +-- checkGlobalBlock (METADATA_READ)
                    +-- checkRequestBlock (METADATA_READ)
                    +-- shards() (allShardsIncludingRelocationTargets)
                    +-- shardOperation()
                    |       |
                    |       +-- IndicesService.indexServiceSafe()
                    |       +-- IndexService.getShard()
                    |       +-- IndexShard.recoveryState()
                    |
                    +-- newResponse() (グルーピング・フィルタリング)
                            |
                            +-- RecoveryResponse生成
```

### データフロー図

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

REST Request         --> RecoveryRequest生成               --> ブロードキャストリクエスト
  (detailed,               +-> 各ノードに配信
   active_only)

各シャード            --> IndexShard.recoveryState()        --> RecoveryState

RecoveryState群      --> newResponse()                      --> RecoveryResponse
                          +-> nullフィルタリング                  {index: [RecoveryState, ...]}
                          +-> activeOnlyフィルタリング
                          +-> インデックス別グルーピング
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RecoveryAction.java | `server/src/main/java/org/opensearch/action/admin/indices/recovery/RecoveryAction.java` | ソース | アクション定義 |
| RecoveryRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/recovery/RecoveryRequest.java` | ソース | リクエストデータ構造 |
| RecoveryResponse.java | `server/src/main/java/org/opensearch/action/admin/indices/recovery/RecoveryResponse.java` | ソース | レスポンスデータ構造 |
| RecoveryRequestBuilder.java | `server/src/main/java/org/opensearch/action/admin/indices/recovery/RecoveryRequestBuilder.java` | ソース | リクエストビルダー |
| TransportRecoveryAction.java | `server/src/main/java/org/opensearch/action/admin/indices/recovery/TransportRecoveryAction.java` | ソース | トランスポートアクション |
| RecoveryState.java | `server/src/main/java/org/opensearch/indices/recovery/RecoveryState.java` | ソース | リカバリ状態データ構造 |
