# 機能設計書 6-インデックスシュリンク/スプリット

## 概要

本ドキュメントは、OpenSearchにおけるインデックスシュリンク/スプリット機能の設計を記述する。既存インデックスのシャード数を減少（シュリンク）または増加（スプリット）する機能である。

### 本機能の処理概要

インデックスシュリンク/スプリット機能は、既存のインデックスから新しいインデックスを作成し、プライマリシャード数を変更する。シュリンクは複数のシャードを1つに統合し、スプリットは1つのシャードを複数に分割する。クローン操作（シャード数維持のコピー）も同じ基盤で実現される。

**業務上の目的・背景**：初期に設定したシャード数が適切でない場合や、データ量の変化に応じてシャード数を調整する必要がある場合に使用する。シュリンクにより不要なシャードを統合してリソースを節約し、スプリットにより書き込みスループットを向上させる。

**機能の利用シーン**：過剰なシャード数を持つインデックスの最適化（シュリンク）、データ量増加に伴うシャード数の拡張（スプリット）、インデックスのクローン作成。

**主要な処理内容**：
1. ソースインデックスの統計情報取得（ドキュメント数、ストアサイズ）
2. リサイズタイプに応じたバリデーション
3. ターゲットシャード数の計算
4. CreateIndexClusterStateUpdateRequestの構築
5. MetadataCreateIndexServiceを介した新インデックスの作成
6. ソースインデックスからのデータリカバリ

**関連システム・外部連携**：セグメントレプリケーションが有効な場合、シュリンク前にリフレッシュとレプリケーション完了を確認する。リモートストアマイグレーション中の制限がある。

**権限による制御**：ソースインデックスへの読み取り権限と、ターゲットインデックス作成権限（`indices:admin/create`）が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 46 | インデックス縮小 | 主画面 | 既存インデックスをプライマリシャードの少ない新インデックスに縮小する処理 |
| 47 | インデックス分割 | 主画面 | 既存インデックスをプライマリシャードの多い新インデックスに分割する処理 |

## 機能種別

CRUD操作（Create）/ データ変換

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| sourceIndex | String | Yes | ソースインデックス名 | 存在するインデックスであること |
| targetIndexRequest | CreateIndexRequest | Yes | ターゲットインデックスの設定 | index名が必須 |
| type | ResizeType | Yes | SHRINK / SPLIT / CLONE | 有効なリサイズタイプ |
| copySettings | Boolean | No | ソース設定のコピー | デフォルトtrue |
| maxShardSize | ByteSizeValue | No | シュリンク時の最大シャードサイズ | シュリンク時のみ有効 |
| settings | Settings | No | ターゲットインデックスの設定 | - |
| aliases | Set\<Alias\> | No | ターゲットインデックスのエイリアス | - |

### 入力データソース

REST API（POST /{index}/_shrink/{target}, POST /{index}/_split/{target}, POST /{index}/_clone/{target}）。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| acknowledged | boolean | クラスタ状態更新が承認されたか |
| shards_acknowledged | boolean | アクティブシャードが開始されたか |
| index | String | 作成されたターゲットインデックス名 |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. ソースインデックスのバリデーション
   └─ 存在確認、ウォームインデックスでないことの確認
2. リモートマイグレーション検証
   └─ MIXEDモードでの制限チェック
3. （セグレプ有効+シュリンク時）リフレッシュ実行
   └─ レプリケーション完了確認（maxBytesBehind == 0）
4. ソースインデックスの統計取得
   └─ ドキュメント数、ストアサイズの取得
5. ターゲットシャード数の計算
   └─ シュリンク: maxShardSizeに基づく計算 or ユーザ指定
   └─ スプリット: ユーザ指定（必須）
   └─ クローン: ソースと同じ
6. シャードごとのバリデーション
   └─ シュリンク: 統合後のドキュメント数がMAX_DOCS以下
   └─ スプリット/クローン: シャード選択の妥当性
7. CreateIndexClusterStateUpdateRequestの構築
8. MetadataCreateIndexService.createIndex()呼び出し
9. ResizeResponseの返却
```

### フローチャート

```mermaid
flowchart TD
    A[REST API リクエスト受信] --> B{ウォームインデックス?}
    B -->|Yes| ERR1[IllegalStateException]
    B -->|No| C[リモートマイグレーション検証]
    C --> D{セグレプ有効+シュリンク?}
    D -->|Yes| E[リフレッシュ+レプリケーション確認]
    D -->|No| F[インデックス統計取得]
    E --> F
    F --> G[ターゲットシャード数計算]
    G --> H[シャードバリデーション]
    H --> I[CreateIndexClusterStateUpdateRequest構築]
    I --> J[MetadataCreateIndexService.createIndex]
    J --> K[ResizeResponse返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | ウォームインデックス制限 | ウォームインデックスはリサイズ不可 | 常時 |
| BR-02 | リモートマイグレーション制限 | MIXEDモードでリモートストア設定とマイグレーション方向が不整合の場合は拒否 | MIXEDモード時 |
| BR-03 | シュリンク時のドキュメント数上限 | 統合後のシャードのドキュメント数がIndexWriter.MAX_DOCSを超えてはならない | シュリンク時 |
| BR-04 | スプリット時のシャード数指定必須 | スプリットではターゲットシャード数の明示的な指定が必要 | スプリット時 |
| BR-05 | read_only設定の伝搬チェック | ソースのindex.blocks.read_onlyがtrueの場合、ターゲットで明示的にfalseに設定しなければエラー | 常時 |
| BR-06 | soft_deletes無効化禁止 | リサイズ時にsoft_deletesを無効化することは不可 | 常時 |

### 計算ロジック

シュリンクのターゲットシャード数計算（calculateTargetIndexShardsNum）:
- `minShards = ceil(sourceStorageSize / maxShardSize)`
- `minShards >= sourceShards`の場合: `targetShards = sourceShards`
- それ以外: `sourceShards`の因数のうち`minShards`以上の最小値

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| リサイズ | ClusterState.metadata | INSERT | 新インデックスメタデータの追加（recoverFromで元インデックスを参照） |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | IllegalStateException | ウォームインデックスのリサイズ | 通常インデックスを使用 |
| 400 | IllegalStateException | リモートマイグレーション不整合 | マイグレーション完了後に実行 |
| 400 | IllegalStateException | シュリンク時MAX_DOCS超過 | より大きなシャード数を指定 |
| 400 | IllegalStateException | セグメントレプリケーション未完了 | レプリケーション完了を待つ |
| 400 | IllegalArgumentException | read_only設定の伝搬問題 | ターゲットでread_only=falseを設定 |
| 404 | IndexNotFoundException | ソースインデックスが存在しない | インデックス名を確認 |

### リトライ仕様

TransportClusterManagerNodeActionの標準リトライ機構が適用される。

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

新インデックスの作成はMetadataCreateIndexServiceを介してアトミックに実行される。ソースインデックスからのデータリカバリは非同期で行われる。

## パフォーマンス要件

シュリンク/スプリットはソースインデックスのデータをコピーするため、データ量に比例した処理時間が必要。シュリンク前にソースインデックスはread-onlyに設定し、全シャードが同一ノードに配置されている必要がある。

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

- ソースインデックスへの読み取り権限が必要
- ターゲットインデックス作成権限（`indices:admin/create`）が必要

## 備考

- ResizeActionのアクション名は`indices:admin/resize`
- ResizeType: SHRINK, SPLIT, CLONE の3種類
- シュリンクの前提条件：ソースインデックスがread-only、全プライマリシャードが同一ノードに配置

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ResizeRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeRequest.java` | sourceIndex, targetIndexRequest, type(ResizeType), copySettings, maxShardSize |
| 1-2 | ResizeType.java | `server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeType.java` | SHRINK, SPLIT, CLONEの列挙型 |
| 1-3 | ResizeResponse.java | `server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeResponse.java` | CreateIndexResponseを継承 |

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | TransportResizeAction.java | `server/src/main/java/org/opensearch/action/admin/indices/shrink/TransportResizeAction.java` | メイン処理ロジック |

**主要処理フロー**:
- **145-233行目**: clusterManagerOperation() -- メイン処理
- **155-157行目**: ウォームインデックスチェック
- **160-163行目**: セグメントレプリケーション有効時のリフレッシュ処理
- **245-351行目**: prepareCreateIndexRequest() -- リクエスト構築の静的メソッド
- **363-391行目**: calculateTargetIndexShardsNum() -- シュリンクのシャード数計算
- **410-431行目**: validateRemoteMigrationModeSettings() -- リモートマイグレーション検証

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

```
REST API (POST /{index}/_shrink/{target})
    |
    +-- TransportResizeAction
          |
          +-- clusterManagerOperation()
                |
                +-- ウォームインデックスチェック
                +-- (セグレプ+シュリンク) リフレッシュ + レプリケーション確認
                +-- IndicesStatsRequest (統計取得)
                +-- prepareCreateIndexRequest()
                |     +-- validateRemoteMigrationModeSettings()
                |     +-- シャード数計算
                |     +-- シャードバリデーション
                |     +-- CreateIndexClusterStateUpdateRequest構築
                |
                +-- MetadataCreateIndexService.createIndex()
```

### データフロー図

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

ResizeRequest ----------> TransportResizeAction -----------> ResizeResponse
 (sourceIndex,             |                                 (acknowledged,
  targetIndexRequest,      +-> IndicesStatsRequest            shards_acknowledged,
  type,                    +-> prepareCreateIndexRequest()    index)
  maxShardSize)            +-> MetadataCreateIndexService.createIndex()
                                |
                                +-> ClusterState更新
                                     (新IndexMetadata追加,
                                      recoverFrom設定)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ResizeAction.java | `server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeAction.java` | ソース | アクション型定義 |
| ResizeRequest.java | `server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeRequest.java` | ソース | リクエスト構造 |
| ResizeResponse.java | `server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeResponse.java` | ソース | レスポンス構造 |
| ResizeType.java | `server/src/main/java/org/opensearch/action/admin/indices/shrink/ResizeType.java` | ソース | リサイズ種別列挙型 |
| TransportResizeAction.java | `server/src/main/java/org/opensearch/action/admin/indices/shrink/TransportResizeAction.java` | ソース | トランスポートアクション |
| MetadataCreateIndexService.java | `server/src/main/java/org/opensearch/cluster/metadata/MetadataCreateIndexService.java` | ソース | インデックス作成ロジック |
