# 画面設計書 101-重み付きルーティング取得

## 概要

本ドキュメントは、OpenSearchクラスタにおける重み付きシャードルーティングの重み設定を取得するREST APIエンドポイント `GET /_cluster/routing/awareness/{attribute}/weights` の設計を記述する。

### 本画面の処理概要

本APIは、Weighted Round-Robin方式のシャードルーティングポリシーにおいて設定されている重み情報を取得するためのエンドポイントである。

**業務上の目的・背景**：マルチゾーン構成のOpenSearchクラスタにおいて、特定のアベイラビリティゾーンに対するトラフィック分散比率を制御するために、重み付きルーティングが使用される。本APIは、現在設定されている重みを確認し、トラフィック制御の状態を把握するために必要である。運用者がルーティング設定の整合性を検証する際や、障害対応時のトラフィック偏りの確認に利用される。

**画面へのアクセス方法**：HTTPクライアント（curl、Kibana Dev Tools等）から `GET /_cluster/routing/awareness/{attribute}/weights` エンドポイントにGETリクエストを送信する。`{attribute}` にはアウェアネス属性名（例: `zone`）を指定する。

**主要な操作・処理内容**：
1. クライアントからGETリクエストを受信し、URLパスパラメータからアウェアネス属性名を抽出する
2. クラスタマネージャノードにリクエストを転送し、クラスタ状態メタデータから `WeightedRoutingMetadata` を取得する
3. 取得した重み情報（各ゾーンの重み値、バージョン、クラスタマネージャ発見状態）をJSONレスポンスとして返却する

**画面遷移**：本APIは単独で動作する情報取得エンドポイントである。関連するAPIとして、重みを設定する `PUT /_cluster/routing/awareness/{attribute}/weights`（No.102）、重みを削除する `DELETE /_cluster/routing/awareness/weights`（No.103）がある。

**権限による表示制御**：クラスタレベルのメタデータ読み取り権限が必要である。クラスタブロック（METADATA_READ）が設定されている場合はリクエストが拒否される。

## 関連機能

| 機能No | 機能名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 58 | 重み付きルーティング | 主機能 | 重み付きシャードルーティングの重みを取得する処理 |

## 画面種別

情報取得（GET）API

## URL/ルーティング

| メソッド | パス | 説明 |
|---------|------|------|
| GET | `/_cluster/routing/awareness/{attribute}/weights` | 指定アウェアネス属性の重み情報を取得 |

## 入出力項目

### パスパラメータ

| パラメータ名 | 型 | 必須 | 説明 |
|-------------|-----|------|------|
| attribute | string | Yes | アウェアネス属性名（例: `zone`） |

### クエリパラメータ

| パラメータ名 | 型 | 必須 | デフォルト | 説明 |
|-------------|-----|------|-----------|------|
| local | boolean | No | false | ローカルノードの情報のみを返すかどうか |

## 表示項目

### レスポンスボディ

| フィールド | 型 | 説明 |
|-----------|-----|------|
| weights | object | ゾーン名をキー、重み値（Double）を値とするマップ |
| _version | long | 重み設定のバージョン番号 |
| discovered_cluster_manager | boolean | クラスタマネージャノードが発見されたかどうか |

### レスポンス例

```json
{
  "weights": {
    "zone-a": "1.0",
    "zone-b": "1.0",
    "zone-c": "0.0"
  },
  "_version": 3,
  "discovered_cluster_manager": true
}
```

## イベント仕様

### 1-GETリクエスト受信

1. `RestClusterGetWeightedRoutingAction.prepareRequest()` がリクエストを受信する
2. URLパスから `attribute` パラメータを抽出し `ClusterGetWeightedRoutingRequest` を生成する
3. `local` パラメータを設定する
4. `NodeClient` 経由で `TransportGetWeightedRoutingAction` にリクエストを転送する
5. クラスタマネージャノードで `clusterManagerOperation()` が実行される
6. `WeightedRoutingService.verifyAwarenessAttribute()` で属性名の妥当性を検証する
7. `ClusterState.metadata().custom(WeightedRoutingMetadata.TYPE)` から重みメタデータを取得する
8. `ClusterGetWeightedRoutingResponse` を構築してレスポンスを返却する

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

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

| 操作（イベント） | 対象テーブル | 操作種別 | 概要 |
|----------------|-------------|---------|------|
| GETリクエスト | ClusterState（メモリ内） | SELECT | クラスタ状態メタデータからWeightedRoutingMetadataを読み取り |

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

#### ClusterState Metadata

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| SELECT | WeightedRoutingMetadata | custom(WeightedRoutingMetadata.TYPE) | クラスタ状態のカスタムメタデータから取得 |

## メッセージ仕様

| 種別 | メッセージ | 条件 |
|------|----------|------|
| エラー | "Awareness attribute is missing" | attribute パラメータが未指定またはnullの場合 |
| エラー | ClusterBlockException | クラスタがMETADATA_READブロック中の場合 |
| 成功 | 200 OK + JSONレスポンス | 正常に重みを取得できた場合 |

## 例外処理

| 例外条件 | HTTPステータス | レスポンス内容 |
|---------|---------------|---------------|
| アウェアネス属性名未指定 | 400 Bad Request | バリデーションエラーメッセージ |
| クラスタブロック中 | 403 Forbidden | ClusterBlockException |
| 重み未設定 | 200 OK | 空のレスポンスオブジェクト |
| クラスタマネージャノード未発見 | 503 Service Unavailable | MasterNotDiscoveredException |

## 備考

- 本APIはOpenSearch 2.4.0以降で利用可能（`@PublicApi(since = "2.4.0")`）
- 重みが未設定の場合でも200レスポンスが返るが、weightsフィールドは含まれない
- `local` パラメータを使用するとクラスタマネージャノードへの転送を省略してローカルノードのクラスタ状態から情報を取得できる

---

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

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

### 推奨読解順序

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

まず、重み付きルーティングに関連するデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ClusterGetWeightedRoutingRequest.java | `server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/get/ClusterGetWeightedRoutingRequest.java` | リクエストの構造。`awarenessAttribute` フィールドとバリデーションロジック |
| 1-2 | ClusterGetWeightedRoutingResponse.java | `server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/get/ClusterGetWeightedRoutingResponse.java` | レスポンスの構造。`WeightedRouting`, `version`, `discoveredClusterManager` フィールドと `toXContent()` によるJSON化 |
| 1-3 | WeightedRouting.java | `server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java` | 重み付きルーティングの本体データ構造。属性名と重みマップ |

**読解のコツ**: `ClusterGetWeightedRoutingResponse` の `toXContent()` メソッド（行100-116）がレスポンスJSONの形式を決定している。

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

処理の起点となるRESTアクションハンドラを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | RestClusterGetWeightedRoutingAction.java | `server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterGetWeightedRoutingAction.java` | ルート定義（行38）とリクエスト処理（行47-51） |

**主要処理フロー**:
1. **行38**: `GET /_cluster/routing/awareness/{attribute}/weights` のルートを登録
2. **行48**: `request.param("attribute")` でパスパラメータを取得し `ClusterGetWeightedRoutingRequest` を生成
3. **行49**: `local` パラメータを設定
4. **行50**: `client.admin().cluster().getWeightedRouting()` で Transport層に処理を委譲

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

クラスタマネージャノードで実行されるビジネスロジックを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | TransportGetWeightedRoutingAction.java | `server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/get/TransportGetWeightedRoutingAction.java` | `clusterManagerOperation()` メソッド（行80-101）がメイン処理 |

**主要処理フロー**:
- **行86**: `weightedRoutingService.verifyAwarenessAttribute()` でアウェアネス属性の検証
- **行87**: `state.metadata().custom(WeightedRoutingMetadata.TYPE)` でメタデータ取得
- **行90-95**: 重みデータが存在する場合にレスポンスオブジェクトを構築
- **行97**: リスナーにレスポンスを返却

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

```
RestClusterGetWeightedRoutingAction.prepareRequest()
    |
    +-- ClusterGetWeightedRoutingRequest(attribute)
    |
    +-- NodeClient.admin().cluster().getWeightedRouting()
            |
            +-- TransportGetWeightedRoutingAction.clusterManagerOperation()
                    |
                    +-- WeightedRoutingService.verifyAwarenessAttribute()
                    |
                    +-- ClusterState.metadata().custom(WeightedRoutingMetadata.TYPE)
                    |
                    +-- ClusterGetWeightedRoutingResponse(weightedRouting, discovered, version)
```

### データフロー図

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

GET request          --> RestClusterGetWeightedRoutingAction   --> ClusterGetWeightedRoutingRequest
  attribute param        .prepareRequest()

                     --> TransportGetWeightedRoutingAction     --> ClusterGetWeightedRoutingResponse
                         .clusterManagerOperation()                 { weights, _version,
                         ClusterState.metadata                       discovered_cluster_manager }
                           .custom(WeightedRoutingMetadata)

                     --> RestToXContentListener               --> HTTP 200 JSON Response
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| RestClusterGetWeightedRoutingAction.java | `server/src/main/java/org/opensearch/rest/action/admin/cluster/RestClusterGetWeightedRoutingAction.java` | ソース | RESTエンドポイント定義・リクエスト処理 |
| ClusterGetWeightedRoutingRequest.java | `server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/get/ClusterGetWeightedRoutingRequest.java` | ソース | リクエストオブジェクト定義 |
| ClusterGetWeightedRoutingResponse.java | `server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/get/ClusterGetWeightedRoutingResponse.java` | ソース | レスポンスオブジェクト定義・JSON化 |
| ClusterGetWeightedRoutingAction.java | `server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/get/ClusterGetWeightedRoutingAction.java` | ソース | アクション名定義 |
| TransportGetWeightedRoutingAction.java | `server/src/main/java/org/opensearch/action/admin/cluster/shards/routing/weighted/get/TransportGetWeightedRoutingAction.java` | ソース | Transport層ビジネスロジック |
| WeightedRoutingMetadata.java | `server/src/main/java/org/opensearch/cluster/metadata/WeightedRoutingMetadata.java` | ソース | クラスタメタデータ内の重み保持 |
| WeightedRouting.java | `server/src/main/java/org/opensearch/cluster/routing/WeightedRouting.java` | ソース | 重み付きルーティングデータ構造 |
| WeightedRoutingService.java | `server/src/main/java/org/opensearch/cluster/routing/WeightedRoutingService.java` | ソース | 重み付きルーティングサービス（検証含む） |
| cluster.get_weighted_routing.json | `rest-api-spec/src/main/resources/rest-api-spec/api/cluster.get_weighted_routing.json` | 設定 | REST APIスペック定義 |
