# 画面設計書 130-Danglingインデックス削除

## 概要

本ドキュメントは、OpenSearchのDanglingインデックス削除API（DELETE /_dangling/{index_uuid}）の画面設計書である。指定されたDanglingインデックスを完全に削除するREST APIエンドポイントの仕様を定義する。

### 本画面の処理概要

**業務上の目的・背景**：Danglingインデックスはクラスタ状態に登録されていないがノードのローカルディスクに存在するインデックスである。不要なDanglingインデックスがディスク容量を消費し続けることを防ぐため、明示的に削除する手段が必要である。本APIはDanglingインデックスをクラスタの「インデックス墓地（Index Graveyard）」に追加することで、今後そのインデックスが再びインポートされることを防ぎ、各ノードでのローカルデータの削除を促す。データ損失のリスクを伴うため、accept_data_loss=trueの明示的な同意が必要である。

**画面へのアクセス方法**：REST APIクライアントから `DELETE /_dangling/{index_uuid}?accept_data_loss=true` エンドポイントにHTTP DELETEリクエストを送信してアクセスする。事前にDanglingインデックス一覧API（GET /_dangling）でUUIDを確認する。

**主要な操作・処理内容**：
1. クライアントがDanglingインデックスのUUIDとaccept_data_loss=trueを指定してDELETEリクエストを送信する
2. ListDanglingIndicesActionで全ノードからDanglingインデックスの存在を確認する
3. accept_data_loss=falseの場合はエラーを返却する
4. クラスタ状態更新タスクを投入し、インデックスをIndex Graveyardに追加する
5. Index Graveyardに登録されたインデックスは各ノードで自動的にローカルデータが削除される
6. 成功時にHTTP 202 Acceptedで応答する

**画面遷移**：Danglingインデックス一覧（GET /_dangling）でUUIDを確認し、本APIで削除を実行する。Danglingインデックスインポート（POST /_dangling/{index_uuid}）と排他的な操作であり、インポートか削除のいずれかを選択する。

**権限による表示制御**：クラスタレベルの管理権限が必要。データ損失の可能性があるため、accept_data_lossパラメータの明示的な指定が必須。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 2 | インデックス削除 | 主機能 | 指定したDanglingインデックスを削除する処理 |

## 画面種別

削除（REST API - データ削除）

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| DELETE | `/_dangling/{index_uuid}` | 指定したDanglingインデックスを削除 |

## 入出力項目

### パスパラメータ

| 項目名 | 型 | 必須 | 説明 |
|--------|------|------|------|
| index_uuid | string | Yes | DanglingインデックスのUUID |

### クエリパラメータ

| 項目名 | 型 | 必須 | デフォルト | 説明 |
|--------|------|------|-----------|------|
| accept_data_loss | boolean | Yes | false | データ損失を許容するか。trueに設定しないと削除不可 |
| timeout | time | No | 30s | 操作タイムアウト |
| cluster_manager_timeout | time | No | 30s | クラスタマネージャノードへの接続タイムアウト |
| master_timeout | time | No | 30s | （非推奨）cluster_manager_timeout を使用すること |

## 表示項目

### レスポンスボディ

| 項目名 | 型 | 説明 |
|--------|------|------|
| acknowledged | boolean | リクエストが受理されたかどうか |

## イベント仕様

### 1-Danglingインデックス削除リクエスト

クライアントからDELETEリクエストを受信すると以下の処理が実行される：

1. RestDeleteDanglingIndexActionがリクエストパラメータを解析し、DeleteDanglingIndexRequestを生成する（index_uuid, accept_data_loss）
2. timeout、cluster_manager_timeoutパラメータを設定する
3. TransportDeleteDanglingIndexAction（TransportClusterManagerNodeAction）がクラスタマネージャノードで実行される
4. ListDanglingIndicesActionを使用して全ノードからDanglingインデックスの存在を確認する
5. accept_data_loss=falseの場合はエラーを返却する
6. AckedClusterStateUpdateTaskを投入してクラスタ状態を更新する
7. Index GraveyardにインデックスのUUIDと名前を追加する
8. 各ノードがIndex Graveyardを参照し、該当インデックスのローカルデータを削除する
9. 成功時にHTTP 202 Acceptedで応答する

## データベース更新仕様

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| DELETE リクエスト | クラスタ状態（Metadata.IndexGraveyard） | INSERT | インデックスをIndex Graveyardに追加 |
| DELETE リクエスト | ノードローカルデータ | DELETE | 各ノードがIndex Graveyardに基づきローカルデータを自動削除 |

### テーブル別更新項目詳細

#### クラスタ状態（Index Graveyard）

| 操作 | 項目 | 更新値・取得条件 | 備考 |
|-----|------|-----------------|------|
| INSERT | IndexGraveyard.tombstones | Index（UUID, name）を追加 | Graveyardに登録されたインデックスは再インポート不可 |

## メッセージ仕様

| HTTPステータス | 条件 | メッセージ例 |
|---------------|------|-------------|
| 202 Accepted | 削除受理 | `{"acknowledged": true}` |
| 400 Bad Request | accept_data_loss=falseまたは未指定 | `must accept data loss` |
| 404 Not Found | 指定UUIDのDanglingインデックスが見つからない | Danglingインデックスが存在しない |
| 500 Internal Server Error | 削除処理中のエラー | 内部エラー |

## 例外処理

| 例外 | 条件 | 対処 |
|------|------|------|
| IllegalArgumentException | accept_data_loss=falseまたは未指定 | 400を返却 |
| OpenSearchException | Danglingインデックスが見つからない | 404を返却 |
| ClusterBlockException | クラスタブロックが設定されている | 処理をブロック |
| FailedNodeException | ノード通信失敗（一覧取得時） | エラー情報をログに記録 |

## 備考

- accept_data_loss=trueの指定は必須。データ損失のリスクがあることをユーザーが明示的に了承するセーフティガード
- HTTPレスポンスは202 Accepted（通常の200 OKではない）で返却される
- Index Graveyardに登録されたインデックスは、今後同じUUIDでDanglingインデックスとして再発見されてもインポートされない
- TransportDeleteDanglingIndexActionはTransportClusterManagerNodeActionを継承しており、クラスタマネージャノードで実行される
- クラスタ状態更新はClusterManagerTaskThrottlerにより制御される
- `master_timeout` パラメータはバージョン2.0.0で非推奨

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | DeleteDanglingIndexRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/dangling/delete/DeleteDanglingIndexRequest.java` | リクエストパラメータ（indexUUID, acceptDataLoss）の定義 |
| 1-2 | IndexGraveyard.java | `server/src/main/java/org/opensearch/cluster/metadata/IndexGraveyard.java` | Index Graveyardのデータ構造。削除されたインデックスのtombstone管理 |

**読解のコツ**: IndexGraveyardはクラスタMetadata内に保持され、削除されたインデックスのUUIDと名前のリスト（tombstones）を管理する。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestDeleteDanglingIndexAction.java | `server/src/main/java/org/opensearch/rest/action/admin/cluster/dangling/RestDeleteDanglingIndexAction.java` | ルーティング定義（62行目）とリクエスト解析（71-88行目） |

**主要処理フロー**:
1. **62行目**: `DELETE /_dangling/{index_uuid}` のルーティング定義
2. **72-75行目**: DeleteDanglingIndexRequestを生成（index_uuid, accept_data_loss）
3. **77-79行目**: timeout、cluster_manager_timeoutを設定
4. **81-88行目**: NodeClient経由でdeleteDanglingIndexアクションを実行。レスポンスステータスは202 ACCEPTED

#### Step 3: Transport層の処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TransportDeleteDanglingIndexAction.java | `server/src/main/java/org/opensearch/action/admin/indices/dangling/delete/TransportDeleteDanglingIndexAction.java` | TransportClusterManagerNodeActionを継承。ListDanglingIndicesActionで存在確認後、AckedClusterStateUpdateTaskでIndex Graveyardに追加 |

#### Step 4: クラスタ状態更新を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | IndexGraveyard.java | `server/src/main/java/org/opensearch/cluster/metadata/IndexGraveyard.java` | Index Graveyardの構造とtombstoneの追加ロジック |
| 4-2 | AckedClusterStateUpdateTask.java | `server/src/main/java/org/opensearch/cluster/AckedClusterStateUpdateTask.java` | クラスタ状態更新タスクの基底クラス |

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

```
RestDeleteDanglingIndexAction#prepareRequest()
    |
    +-- NodeClient#admin().cluster().deleteDanglingIndex()
            |
            +-- TransportDeleteDanglingIndexAction#clusterManagerOperation()
                    |
                    +-- ListDanglingIndicesAction (全ノードからDangling確認)
                    |       |
                    |       +-- 各ノード: DanglingIndicesState
                    |
                    +-- accept_data_lossチェック
                    |
                    +-- AckedClusterStateUpdateTask投入
                            |
                            +-- Metadata.Builder
                            |       |
                            |       +-- IndexGraveyard.Builder
                            |               (tombstone追加)
                            |
                            +-- ClusterState更新
```

### データフロー図

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

DELETE /_dangling/           RestDeleteDanglingIndexAction     AcknowledgedResponse
  {index_uuid}               (パラメータ解析)                    (HTTP 202)
  ?accept_data_loss=true            |                           {"acknowledged": true}
                                    v
                        TransportDeleteDanglingIndexAction
                        (クラスタマネージャノード)
                                    |
                        ListDanglingIndicesAction
                        (Dangling存在確認)
                                    |
                        AckedClusterStateUpdateTask
                        (クラスタ状態更新)
                                    |
                        IndexGraveyard更新
                        (tombstone追加)
                                    |
                        各ノード自動削除
                        (ローカルデータ)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestDeleteDanglingIndexAction.java | `server/src/main/java/org/opensearch/rest/action/admin/cluster/dangling/RestDeleteDanglingIndexAction.java` | ソース | RESTハンドラ |
| TransportDeleteDanglingIndexAction.java | `server/src/main/java/org/opensearch/action/admin/indices/dangling/delete/TransportDeleteDanglingIndexAction.java` | ソース | Transportアクション（クラスタマネージャノード型） |
| DeleteDanglingIndexRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/dangling/delete/DeleteDanglingIndexRequest.java` | ソース | リクエストモデル |
| IndexGraveyard.java | `server/src/main/java/org/opensearch/cluster/metadata/IndexGraveyard.java` | ソース | Index Graveyard管理 |
| ListDanglingIndicesAction.java | `server/src/main/java/org/opensearch/action/admin/indices/dangling/list/ListDanglingIndicesAction.java` | ソース | Dangling一覧取得（存在確認に使用） |
| DanglingIndicesState.java | `server/src/main/java/org/opensearch/gateway/DanglingIndicesState.java` | ソース | Danglingインデックス状態管理 |
| dangling_indices.delete_dangling_index.json | `rest-api-spec/src/main/resources/rest-api-spec/api/dangling_indices.delete_dangling_index.json` | API定義 | REST API仕様定義 |
