# 機能設計書 14-リインデックス

## 概要

本ドキュメントは、OpenSearchの「リインデックス」機能の設計を記述する。既存インデックスから別のインデックスへドキュメントをコピーするReindex APIの処理仕様を定義する。

### 本機能の処理概要

本機能は、ソースインデックスからドキュメントを検索で取得し、デスティネーションインデックスへバルク操作で書き込むことでドキュメントをコピーする機能である。REST APIの `POST /_reindex` エンドポイントを通じて呼び出される。

**業務上の目的・背景**：インデックスのマッピング変更、シャード数の変更、アナライザの変更など、既存インデックスの構造変更が必要な場合にデータを新しいインデックスへ移行する需要がある。また、リモートクラスタからのデータ移行にも利用される。

**機能の利用シーン**：マッピング変更を伴うインデックス再構築、インデックス統合・分割、リモートクラスタ間のデータ移行、スクリプトを用いたドキュメント変換付きコピーで利用される。

**主要な処理内容**：
1. ソースインデックスからスクロール検索でドキュメントを順次取得
2. オプションのスクリプトによるドキュメント変換
3. デスティネーションインデックスへバルク操作で書き込み
4. スロットリングによる負荷制御
5. タスクとしての非同期実行と進捗管理

**関連システム・外部連携**：リモートクラスタからのリインデックスをサポート。RemoteInfo設定によりリモートOpenSearch/Elasticsearchからのデータ取得が可能。

**権限による制御**：アクション名 `indices:data/write/reindex` に基づくセキュリティ権限チェック。ソースインデックスへの読み取り権限とデスティネーションインデックスへの書き込み権限が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 17 | Reindex | 主機能 | あるインデックスから別のインデックスにドキュメントをコピーする主処理 |
| 18 | Reindexスロットル変更 | 主機能 | Reindex操作のリクエスト/秒スロットルを変更する処理 |

## 機能種別

データ連携（インデックス間データコピー）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| source | SearchRequest | Yes | ソースインデックスと検索条件 | ソースインデックス必須 |
| destination | IndexRequest | Yes | デスティネーションインデックスと設定 | デスティネーションインデックス必須 |
| script | Script | No | ドキュメント変換スクリプト | - |
| maxDocs | int | No | コピーする最大ドキュメント数 | - |
| conflicts | String | No | コンフリクト時の動作（proceed/abort） | - |
| remoteInfo | RemoteInfo | No | リモートクラスタ接続情報 | allowlist設定に含まれること |
| requestsPerSecond | float | No | スロットリング（リクエスト/秒） | - |
| slices | int | No | 並列スライス数 | - |
| scroll | TimeValue | No | スクロールのキープアライブ時間 | - |
| timeout | TimeValue | No | タイムアウト | - |
| waitForCompletion | boolean | No | 同期/非同期実行（デフォルト: true） | - |

### 入力データソース

REST APIリクエスト（HTTP POST、JSONボディ）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| took | long | 処理時間（ミリ秒） |
| timed_out | boolean | タイムアウトしたか |
| total | long | 処理対象の総ドキュメント数 |
| updated | long | 更新されたドキュメント数 |
| created | long | 作成されたドキュメント数 |
| deleted | long | 削除されたドキュメント数 |
| batches | int | バッチ処理回数 |
| version_conflicts | long | バージョンコンフリクト数 |
| noops | long | 操作なしの数 |
| retries | Object | リトライ回数（bulk, search） |
| throttled_millis | long | スロットリング待機時間 |
| failures | List | 失敗した操作のリスト |
| task | String | 非同期実行時のタスクID |

### 出力先

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

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信・バリデーション
   └─ ソース・デスティネーションインデックスの検証、リモート接続許可チェック
2. タスク登録
   └─ BulkByScrollTaskとして登録、非同期実行の場合はタスクIDを即時返却
3. ソースからのスクロール検索開始
   └─ SearchRequestを使用してソースインデックスからドキュメントを取得
4. バッチ処理ループ
   └─ 取得したドキュメントをバルク操作でデスティネーションへ書き込み
5. スクリプト適用（オプション）
   └─ 各ドキュメントに対してスクリプトを実行し変換
6. スロットリング（オプション）
   └─ requestsPerSecondに基づく待機
7. 完了・レスポンス返却
   └─ BulkByScrollResponse生成
```

### フローチャート

```mermaid
flowchart TD
    A[Reindex リクエスト受信] --> B{バリデーション OK?}
    B -->|No| C[エラー返却]
    B -->|Yes| D{waitForCompletion?}
    D -->|false| E[タスクID返却]
    D -->|true| F[同期実行開始]
    E --> F
    F --> G[ソースからスクロール検索]
    G --> H{ドキュメントあり?}
    H -->|No| I[完了]
    H -->|Yes| J{スクリプトあり?}
    J -->|Yes| K[スクリプト変換]
    J -->|No| L[バルク書き込み]
    K --> L
    L --> M{スロットリング?}
    M -->|Yes| N[待機]
    M -->|No| G
    N --> G
    I --> O[BulkByScrollResponse 返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-14-01 | リモート許可リスト | リモートリインデックス時はreindex.remote.allowlist設定に含まれるホストのみ接続可能 | remoteInfo指定時 |
| BR-14-02 | コンフリクト処理 | conflicts=proceedの場合バージョンコンフリクトをスキップ、abortの場合は処理中断 | conflicts設定時 |
| BR-14-03 | スライス並列化 | slicesパラメータにより処理を並列化し、各スライスが独立してスクロール検索を実行 | slices > 1 |
| BR-14-04 | スロットリング | requestsPerSecondにより処理速度を制御。Rethrottle APIで実行中のタスクのスロットルを動的変更可能 | requestsPerSecond設定時 |

### 計算ロジック

スロットリングの待機時間は、バッチサイズとrequestsPerSecondから算出される。

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ソース読み取り | ソースLucene Index | SELECT | スクロール検索によるドキュメント読み取り |
| デスティネーション書き込み | デスティネーションLucene Index | INSERT/UPDATE | バルク操作によるドキュメント書き込み |

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

#### ソースLucene Index

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | _source, _id, _routing | 検索クエリ条件 | スクロールによる順次取得 |

#### デスティネーションLucene Index

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INDEX | _source, _id | ソースから取得したドキュメント | バルク書き込み |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 400 | ActionRequestValidationException | ソースまたはデスティネーション未指定 | リクエストパラメータを修正 |
| 403 | 許可リスト外のリモート接続 | リモートホストがallowlistに含まれない | allowlist設定を更新 |
| 409 | VersionConflictEngineException | バージョンコンフリクト（conflicts=abort時） | conflicts=proceedに変更 |
| 408 | タイムアウト | 処理がタイムアウト | タイムアウト値を増加 |

### リトライ仕様

バルク書き込みとスクロール検索にそれぞれリトライメカニズムが備わっている。リモートリインデックス時はRETRY_INITIAL_BACKOFF（デフォルト500ms）からの指数バックオフリトライが適用される。

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

リインデックス全体はアトミックではない。バッチ単位で処理され、途中で失敗した場合は部分的にコピーされた状態となる。failuresフィールドで失敗した操作を確認できる。

## パフォーマンス要件

- slicesパラメータによる並列化でスループット向上が可能
- requestsPerSecondによるスロットリングで本番環境への影響を制御
- スクロールのキープアライブ時間は適切に設定する必要がある

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

- ソースインデックスへのread権限とデスティネーションインデックスへのwrite権限が必要
- リモートリインデックス時はTLS/SSL接続のサポート（ReindexSslConfig）
- リモート接続先はallowlistで制限

## 備考

- ReindexRequestはAbstractBulkIndexByScrollRequest<ReindexRequest>を継承
- スクリプトによりデスティネーションのインデックス名、ID、ルーティングを動的に変更可能
- リモートリインデックスはRemoteInfoクラスで接続情報を管理
- Reindexerクラスが実際のリインデックスロジックを実装

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ReindexRequest.java | `server/src/main/java/org/opensearch/index/reindex/ReindexRequest.java` | source(SearchRequest), destination(IndexRequest), remoteInfo, script等のフィールド定義 |
| 1-2 | BulkByScrollResponse.java | `server/src/main/java/org/opensearch/index/reindex/BulkByScrollResponse.java` | レスポンス構造（took, total, created, updated, deleted, failures等） |
| 1-3 | RemoteInfo.java | `server/src/main/java/org/opensearch/index/reindex/RemoteInfo.java` | リモート接続情報 |
| 1-4 | AbstractBulkByScrollRequest.java | `server/src/main/java/org/opensearch/index/reindex/AbstractBulkByScrollRequest.java` | 共通パラメータ（requestsPerSecond, slices, maxDocs等） |

**読解のコツ**: ReindexRequestはAbstractBulkIndexByScrollRequestを継承しており、Update By QueryやDelete By Queryと共通の基底クラスを持つ。CompositeIndicesRequestも実装している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | ReindexAction.java | `server/src/main/java/org/opensearch/index/reindex/ReindexAction.java` | アクション名定義 |
| 2-2 | TransportReindexAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/TransportReindexAction.java` | リインデックスのトランスポート処理。REMOTE_CLUSTER_ALLOWLIST設定 |

**主要処理フロー**:
1. **63-65行目**: HandledTransportActionを継承
2. **66-71行目**: REMOTE_CLUSTER_ALLOWLIST設定の定義
3. **73-80行目**: REMOTE_REINDEX_RETRY_INITIAL_BACKOFF設定（デフォルト500ms）

#### Step 3: 実処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | Reindexer.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/Reindexer.java` | リインデックスの実際のロジック |
| 3-2 | AbstractAsyncBulkByScrollAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AbstractAsyncBulkByScrollAction.java` | スクロール検索→バルク書き込みの共通処理 |
| 3-3 | ReindexValidator.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/ReindexValidator.java` | リクエストバリデーション |

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

```
REST API (POST /_reindex)
    |
    +-- TransportReindexAction
           |
           +-- Reindexer
                  |
                  +-- AbstractAsyncBulkByScrollAction
                         |
                         +-- ScrollableHitSource (スクロール検索)
                         |      └─ ClientScrollableHitSource / RemoteScrollableHitSource
                         |
                         +-- BulkRequest (バルク書き込み)
                         |
                         +-- ScriptService (スクリプト実行)
```

### データフロー図

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

ReindexRequest         -->  TransportReindexAction         -->  BulkByScrollResponse
 - source                    |                                   - took
 - destination               +-> Reindexer                      - total
 - script                         |                              - created
 - remoteInfo                      +-> スクロール検索              - updated
 - requestsPerSecond               +-> スクリプト変換             - failures
 - slices                          +-> バルク書き込み             - retries
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| ReindexAction.java | `server/src/main/java/org/opensearch/index/reindex/ReindexAction.java` | ソース | アクション型定義 |
| ReindexRequest.java | `server/src/main/java/org/opensearch/index/reindex/ReindexRequest.java` | ソース | リクエスト構造 |
| TransportReindexAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/TransportReindexAction.java` | ソース | トランスポート処理 |
| Reindexer.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/Reindexer.java` | ソース | リインデックスロジック |
| ReindexValidator.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/ReindexValidator.java` | ソース | バリデーション |
| ReindexSslConfig.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/ReindexSslConfig.java` | ソース | SSL設定 |
| AbstractAsyncBulkByScrollAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/AbstractAsyncBulkByScrollAction.java` | ソース | スクロール+バルク共通処理 |
| AbstractBulkByScrollRequest.java | `server/src/main/java/org/opensearch/index/reindex/AbstractBulkByScrollRequest.java` | ソース | 共通リクエスト基底クラス |
| BulkByScrollResponse.java | `server/src/main/java/org/opensearch/index/reindex/BulkByScrollResponse.java` | ソース | レスポンス構造 |
| BulkByScrollTask.java | `server/src/main/java/org/opensearch/index/reindex/BulkByScrollTask.java` | ソース | タスク管理 |
| RemoteInfo.java | `server/src/main/java/org/opensearch/index/reindex/RemoteInfo.java` | ソース | リモート接続情報 |
| ScrollableHitSource.java | `server/src/main/java/org/opensearch/index/reindex/ScrollableHitSource.java` | ソース | スクロール検索抽象化 |
| ClientScrollableHitSource.java | `server/src/main/java/org/opensearch/index/reindex/ClientScrollableHitSource.java` | ソース | ローカルスクロール |
| RestReindexAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/RestReindexAction.java` | ソース | REST APIハンドラー |
| RethrottleAction.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/RethrottleAction.java` | ソース | スロットル変更アクション |
| ReindexModulePlugin.java | `modules/reindex/src/main/java/org/opensearch/index/reindex/ReindexModulePlugin.java` | ソース | プラグイン登録 |
