# 機能設計書 101-ワークロードグループ管理

## 概要

本ドキュメントは、OpenSearchのワークロードグループ管理機能（Workload Group Management）の設計を記述する。リソース使用量に基づくクエリのグループ化・制御を行い、クラスタの安定性を維持するための機能である。

### 本機能の処理概要

**業務上の目的・背景**：マルチテナント環境やリソース共有環境において、特定のクエリやワークロードがCPUやメモリを過剰に消費し、他のワークロードに影響を与える問題を解決する。ワークロードグループにリソース制限を設けることで、各ワークロードの公平なリソース配分を実現し、クラスタ全体の安定運用を可能にする。

**機能の利用シーン**：クエリを論理的なグループに分類し、グループ単位でCPU・メモリの使用量閾値を設定する場面で利用される。閾値を超過した場合には新規リクエストの拒否やタスクのキャンセルが行われ、リソースの過剰消費を防止する。

**主要な処理内容**：
1. ワークロードグループの定義（リソース制限・レジリエンシーモードの設定）
2. クラスタ状態変更検知によるグループの動的追加・削除
3. リソース使用量の定期的な監視と閾値チェック
4. 閾値超過時のタスクキャンセル（ENFORCED/SOFTモード）
5. 新規リクエストの拒否判定（リソース制限に基づく受入制御）
6. ノードレベルのリソース逼迫（duress）状態の検出と対応
7. ワークロードグループ単位の統計情報（completions, rejections, cancellations）の収集

**関連システム・外部連携**：クラスタ状態管理（ClusterService）と連携してワークロードグループの追加・削除を検知する。TaskResourceTrackingServiceと連携してタスクごとのリソース使用量を追跡する。

**権限による制御**：ワークロードグループの作成・更新・削除はクラスタ管理者権限が必要。ワークロードグループへのタスク割り当てはThreadContextヘッダを介して行われる。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 167 | WLM統計一覧 | 主機能 | WLM統計をページネーション付きで返す処理 |

## 機能種別

リソース管理 / タスク制御 / 監視

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| resiliency_mode | String | Yes | レジリエンシーモード（soft/enforced/monitor） | soft, enforced, monitorのいずれか |
| resource_limits.cpu | Double | No | CPUリソース制限値 | 0.0 < value <= 1.0 |
| resource_limits.memory | Double | No | メモリリソース制限値 | 0.0 < value <= 1.0 |
| workloadGroupId | String | No | ワークロードグループID（ThreadContextヘッダ経由） | 未指定時はDEFAULT_WORKLOAD_GROUP |

### 入力データソース

- クラスタメタデータ（WorkloadGroup定義）
- ThreadContextヘッダ（workloadGroupIdの伝搬）
- ノードレベルのCPU/メモリ使用量（ProcessProbe, JvmStats）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| total_completions | long | 完了タスク数 |
| total_rejections | long | 拒否数 |
| total_cancellations | long | キャンセル数 |
| failures | long | 失敗数 |
| cpu.current_usage | double | 現在のCPU使用率 |
| cpu.cancellations | long | CPU起因のキャンセル数 |
| cpu.rejections | long | CPU起因の拒否数 |
| memory.current_usage | double | 現在のメモリ使用率 |
| memory.cancellations | long | メモリ起因のキャンセル数 |
| memory.rejections | long | メモリ起因の拒否数 |

### 出力先

REST APIレスポンス（JSON形式）、内部統計カウンタ

## 処理フロー

### 処理シーケンス

```
1. WorkloadGroupService起動
   └─ スケジューラにより定期実行（デフォルト1秒間隔）
2. WLMモードの確認
   └─ DISABLEDの場合は処理スキップ
3. ENFORCEDモードのグループに対するキャンセル判定
   └─ リソース超過タスクの選択とキャンセル実行
4. ノードduress状態の確認
   └─ duress時は削除済みグループのタスクキャンセル + SOFTモードグループのキャンセル
5. リソース使用量の記録更新
   └─ 各ワークロードグループの現在使用量をstateに記録
6. 新規リクエスト受付時のrejectIfNeeded判定
   └─ 閾値超過の場合OpenSearchRejectedExecutionExceptionを送出
```

### フローチャート

```mermaid
flowchart TD
    A[定期実行 doRun] --> B{WLMモード?}
    B -->|DISABLED| Z[処理終了]
    B -->|ENABLED/MONITOR_ONLY| C[ENFORCEDグループのキャンセル判定]
    C --> D{ノードがduress状態?}
    D -->|Yes| E[削除済みグループのタスクキャンセル]
    E --> F{まだduress?}
    F -->|Yes| G[SOFTグループのキャンセル判定]
    F -->|No| H[リソース使用量記録更新]
    D -->|No| H
    G --> H
    H --> Z
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-101 | リソース制限値バリデーション | resource_limitsの値は0.0より大きく1.0以下 | ワークロードグループ作成・更新時 |
| BR-102 | レジリエンシーモード制御 | SOFTモードはノードduress時のみキャンセル、ENFORCEDは常時キャンセル、MONITORはログのみ | タスクキャンセル判定時 |
| BR-103 | 拒否閾値の正規化 | 拒否閾値 = グループ制限値 * ノードレベル拒否閾値 | リクエスト拒否判定時 |
| BR-104 | キャンセル閾値の正規化 | キャンセル閾値 = グループ制限値 * ノードレベルキャンセル閾値 | タスクキャンセル判定時 |
| BR-105 | 拒否 < キャンセル閾値 | 拒否閾値は常にキャンセル閾値以下 | 設定更新時 |

### 計算ロジック

- 正規化された拒否閾値 = `resource_limit * node_level_rejection_threshold`
- 正規化されたキャンセル閾値 = `resource_limit * node_level_cancellation_threshold`
- duress判定：CPU使用率 > `node_level_cpu_cancellation_threshold` が `duress_streak` 回連続

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| ワークロードグループ登録 | ClusterState Metadata | UPDATE | クラスタメタデータにWorkloadGroup定義を追加 |
| ワークロードグループ削除 | ClusterState Metadata | UPDATE | クラスタメタデータからWorkloadGroup定義を削除 |

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

#### ClusterState Metadata (WorkloadGroups)

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| UPDATE | workloadGroups | WorkloadGroupオブジェクトのMap | クラスタ状態変更イベントで伝搬 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 429 | OpenSearchRejectedExecutionException | ワークロードグループのリソース制限超過 | リクエストをリトライまたは別グループに振り分け |
| 404 | ResourceNotFoundException | 存在しないワークロードグループIDの指定 | 正しいIDを使用 |
| 400 | IllegalArgumentException | リソース制限値が範囲外 | 0.0 < value <= 1.0 の範囲で指定 |

### リトライ仕様

拒否されたリクエストはクライアント側でバックオフ付きリトライを推奨。サーバー側での自動リトライは行わない。

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

ワークロードグループの作成・更新・削除はクラスタ状態変更として処理され、クラスタマネージャノードを通じたコンセンサスで反映される。個々のタスクキャンセルや拒否はトランザクション管理の対象外。

## パフォーマンス要件

- WorkloadGroupServiceの定期実行間隔：デフォルト1000ms（設定変更可能、最小1000ms）
- duress判定のストリーク回数：デフォルト3回（設定変更可能、最小3回）
- タスクキャンセル処理はワーカースレッドで非同期実行

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

- ワークロードグループの作成・削除はクラスタ管理権限が必要
- ワークロードグループIDはThreadContextヘッダで伝搬され、トランスポート層で自動的に設定される
- ノードレベルの閾値設定はcluster settingsとして管理され、動的変更可能

## 備考

- 本機能は `@ExperimentalApi` として提供されており、APIの安定性は保証されていない
- `WlmMode` は `enabled`, `monitor_only`, `disabled` の3モードを持ち、デフォルトは `monitor_only`
- `monitor_only` モードではキャンセル対象の特定とログ記録は行うが、実際のキャンセル・拒否は行わない

---

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

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

### 推奨読解順序

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

まず、ワークロードグループに関連するデータモデルとリソースタイプの定義を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | ResourceType.java | `server/src/main/java/org/opensearch/wlm/ResourceType.java` | CPU/MEMORYの2つのリソースタイプ定義と閾値取得ロジック |
| 1-2 | MutableWorkloadGroupFragment.java | `server/src/main/java/org/opensearch/wlm/MutableWorkloadGroupFragment.java` | ResiliencyMode（SOFT/ENFORCED/MONITOR）とresource_limitsの定義 |
| 1-3 | WorkloadGroupTask.java | `server/src/main/java/org/opensearch/wlm/WorkloadGroupTask.java` | CancellableTaskを継承したタスク基底クラス、workloadGroupIdの管理 |
| 1-4 | WorkloadGroupStats.java | `server/src/main/java/org/opensearch/wlm/stats/WorkloadGroupStats.java` | 統計データの構造（completions, rejections, cancellations, ResourceStats） |

**読解のコツ**: `ResourceType`はenum定義で`CpuUsageCalculator`と`MemoryUsageCalculator`をそれぞれ保持している。`MutableWorkloadGroupFragment.ResiliencyMode`の3種類（SOFT/ENFORCED/MONITOR）のセマンティクスの違いに注目する。

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

WorkloadGroupServiceがライフサイクル管理とリソース監視の中心となる。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | WorkloadGroupService.java | `server/src/main/java/org/opensearch/wlm/WorkloadGroupService.java` | メインサービスクラス。定期実行・クラスタ変更検知・拒否判定のすべてを管理 |
| 2-2 | WorkloadManagementSettings.java | `server/src/main/java/org/opensearch/wlm/WorkloadManagementSettings.java` | 全設定パラメータの定義と動的更新ロジック |
| 2-3 | WlmMode.java | `server/src/main/java/org/opensearch/wlm/WlmMode.java` | ENABLED/MONITOR_ONLY/DISABLEDの3モード定義 |

**主要処理フロー**:
1. **63-120行目**: コンストラクタでNodeDuressTrackersの初期化、CPU/メモリの閾値監視設定
2. **125-131行目**: `doRun()`メソッドが定期実行のエントリーポイント。DISABLEDモードチェック後にタスクキャンセルを実行
3. **157-188行目**: `clusterChanged()`でクラスタ状態の変更を検知し、ワークロードグループの追加・削除を処理
4. **255-313行目**: `rejectIfNeeded()`で新規リクエストの受入判定。ENABLEDモード時のみ拒否実行

#### Step 3: タスクキャンセル処理層を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | WorkloadGroupTaskCancellationService.java | `server/src/main/java/org/opensearch/wlm/cancellation/WorkloadGroupTaskCancellationService.java` | キャンセル対象タスクの選択とキャンセル実行 |
| 3-2 | MaximumResourceTaskSelectionStrategy.java | `server/src/main/java/org/opensearch/wlm/cancellation/MaximumResourceTaskSelectionStrategy.java` | 最大リソース消費タスクから順にキャンセルする戦略 |
| 3-3 | WorkloadGroupResourceUsageTrackerService.java | `server/src/main/java/org/opensearch/wlm/tracker/WorkloadGroupResourceUsageTrackerService.java` | リソース使用量の追跡と集計 |

**主要処理フロー**:
- **80-92行目**: `cancelTasks()`でENFORCEDモードのキャンセル→ノードduress処理→使用量記録更新の順で実行
- **119-139行目**: `handleNodeDuress()`で削除済みグループのタスクキャンセル→SOFTモードグループのキャンセルを順次実行
- **216-233行目**: WLMモードがENABLEDの場合のみ実際のキャンセルを実行、それ以外はログ出力のみ

#### Step 4: リソース使用量計算を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | CpuUsageCalculator.java | `server/src/main/java/org/opensearch/wlm/tracker/CpuUsageCalculator.java` | CPUリソース使用量の計算ロジック |
| 4-2 | MemoryUsageCalculator.java | `server/src/main/java/org/opensearch/wlm/tracker/MemoryUsageCalculator.java` | メモリリソース使用量の計算ロジック |

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

```
WorkloadGroupService.doRun() [定期実行]
    |
    +-- WorkloadGroupTaskCancellationService.cancelTasks()
    |       |
    |       +-- WorkloadGroupResourceUsageTrackerService.constructWorkloadGroupLevelUsageViews()
    |       |       +-- CpuUsageCalculator.calculateResourceUsage()
    |       |       +-- MemoryUsageCalculator.calculateResourceUsage()
    |       |
    |       +-- cancelTasks(ENFORCED, activeWorkloadGroups)
    |       |       +-- getAllCancellableTasks()
    |       |       |       +-- TaskSelectionStrategy.selectTasksForCancellation()
    |       |       +-- TaskCancellation.cancel()
    |       |
    |       +-- handleNodeDuress()
    |       |       +-- NodeDuressTrackers.isNodeInDuress()
    |       |       +-- cancelTasksFromDeletedWorkloadGroups()
    |       |       +-- cancelTasks(SOFT, activeWorkloadGroups)
    |       |
    |       +-- updateResourceUsageInWorkloadGroupState()
    |
    +-- WorkloadGroupTaskCancellationService.pruneDeletedWorkloadGroups()

WorkloadGroupService.rejectIfNeeded() [リクエスト受付時]
    |
    +-- WorkloadGroupsStateAccessor.getWorkloadGroupState()
    +-- getNormalisedRejectionThreshold()
    +-- OpenSearchRejectedExecutionException [拒否時]
```

### データフロー図

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

ThreadContext
  (workloadGroupId)  -----> WorkloadGroupTask
                              |
ProcessProbe                  v
  (CPU使用率)        -----> WorkloadGroupService.doRun()
JvmStats                      |
  (メモリ使用率)     -----> NodeDuressTrackers
                              |
ClusterState                  v
  (WorkloadGroup定義) ---> WorkloadGroupTaskCancellationService
                              |
                              +---> TaskCancellation       ------> タスクキャンセル実行
                              +---> WorkloadGroupState     ------> 統計カウンタ更新
                              +---> rejectIfNeeded()       ------> 429レスポンス
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| WorkloadGroupService.java | `server/src/main/java/org/opensearch/wlm/WorkloadGroupService.java` | ソース | メインサービスクラス |
| WorkloadGroupTask.java | `server/src/main/java/org/opensearch/wlm/WorkloadGroupTask.java` | ソース | ワークロードグループ対応タスク基底クラス |
| ResourceType.java | `server/src/main/java/org/opensearch/wlm/ResourceType.java` | ソース | リソースタイプ定義（CPU/MEMORY） |
| WlmMode.java | `server/src/main/java/org/opensearch/wlm/WlmMode.java` | ソース | WLMモード定義 |
| WorkloadManagementSettings.java | `server/src/main/java/org/opensearch/wlm/WorkloadManagementSettings.java` | ソース | WLM設定クラス |
| MutableWorkloadGroupFragment.java | `server/src/main/java/org/opensearch/wlm/MutableWorkloadGroupFragment.java` | ソース | 更新可能なグループ属性 |
| WorkloadGroupTaskCancellationService.java | `server/src/main/java/org/opensearch/wlm/cancellation/WorkloadGroupTaskCancellationService.java` | ソース | タスクキャンセルサービス |
| MaximumResourceTaskSelectionStrategy.java | `server/src/main/java/org/opensearch/wlm/cancellation/MaximumResourceTaskSelectionStrategy.java` | ソース | キャンセル対象選択戦略 |
| TaskSelectionStrategy.java | `server/src/main/java/org/opensearch/wlm/cancellation/TaskSelectionStrategy.java` | ソース | タスク選択戦略インターフェース |
| WorkloadGroupResourceUsageTrackerService.java | `server/src/main/java/org/opensearch/wlm/tracker/WorkloadGroupResourceUsageTrackerService.java` | ソース | リソース使用量追跡サービス |
| CpuUsageCalculator.java | `server/src/main/java/org/opensearch/wlm/tracker/CpuUsageCalculator.java` | ソース | CPU使用量計算 |
| MemoryUsageCalculator.java | `server/src/main/java/org/opensearch/wlm/tracker/MemoryUsageCalculator.java` | ソース | メモリ使用量計算 |
| WorkloadGroupStats.java | `server/src/main/java/org/opensearch/wlm/stats/WorkloadGroupStats.java` | ソース | 統計データホルダー |
| WorkloadGroupState.java | `server/src/main/java/org/opensearch/wlm/stats/WorkloadGroupState.java` | ソース | ワークロードグループ状態管理 |
| WorkloadGroupLevelResourceUsageView.java | `server/src/main/java/org/opensearch/wlm/WorkloadGroupLevelResourceUsageView.java` | ソース | リソース使用量ビュー |
| WorkloadGroupsStateAccessor.java | `server/src/main/java/org/opensearch/wlm/WorkloadGroupsStateAccessor.java` | ソース | グループ状態アクセサ |
| WorkloadManagementTransportInterceptor.java | `server/src/main/java/org/opensearch/wlm/WorkloadManagementTransportInterceptor.java` | ソース | トランスポート層インターセプタ |
| WorkloadGroupThreadContextStatePropagator.java | `server/src/main/java/org/opensearch/wlm/WorkloadGroupThreadContextStatePropagator.java` | ソース | ThreadContext状態伝搬 |
| WorkloadGroupRequestOperationListener.java | `server/src/main/java/org/opensearch/wlm/listeners/WorkloadGroupRequestOperationListener.java` | ソース | リクエスト操作リスナー |
