# バッチ設計書 27-WorkloadGroupService

## 概要

本ドキュメントは、OpenSearchのWorkloadGroupServiceが提供するワークロードグループのリソース監視・制御バッチ処理の設計を記述する。このバッチはワークロードグループごとのリソース使用状況を定期的に監視し、リソース制限の適用とタスクキャンセルを実行する。

### 本バッチの処理概要

WorkloadGroupServiceは、AbstractLifecycleComponentおよびClusterStateListenerとして実装されたサービスであり、ワークロードグループ（旧Query Group）ごとのCPU・メモリ使用状況を監視する。ノードがリソース逼迫状態（duress）にある場合、リソース制限を超過したワークロードグループのタスクをキャンセルし、削除されたワークロードグループの後処理（prune）を行う。

**業務上の目的・背景**：マルチテナント環境やワークロード分離が求められる環境では、特定のワークロードが過剰にリソースを消費し、他のワークロードに影響を与えることを防止する必要がある。WorkloadGroupServiceは、各ワークロードグループに設定されたリソース制限（CPU、メモリ）を動的に監視・適用し、公平なリソース配分を実現する。これにより、ノイジーネイバー問題を解決し、SLAの維持を可能にする。

**バッチの実行タイミング**：wlm.workload_group.enforcement_interval設定（デフォルト1000ms、最小1000ms）の間隔で定期実行される。

**主要な処理内容**：
1. ワークロード管理モード（WlmMode）がDISABLEDでないことを確認する
2. NodeDuressTrackers経由でノードのリソース逼迫状態を評価する
3. WorkloadGroupTaskCancellationServiceを呼び出してタスクキャンセルを実行する
4. 削除済みワークロードグループの後処理を行う

**前後の処理との関連**：クラスタ状態変更（clusterChanged）によりワークロードグループの追加・削除が検出される。TaskResourceTrackingServiceがタスクのリソース使用量を追跡する。SearchBackpressureServiceとの連携でshouldSBPHandle()によりSBP処理との分担が行われる。

**影響範囲**：ワークロードグループに属する全てのタスク（SearchTask、SearchShardTask等）に影響する。リソース超過時にはタスクのキャンセルや新規リクエストの拒否が行われる。

## バッチ種別

リソース監視・ワークロード制御

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | wlm.workload_group.enforcement_interval（デフォルト1000ms） |
| 実行時刻 | サービス起動後から継続的に実行 |
| 実行曜日 | 該当なし（常時） |
| 実行日 | 該当なし（常時） |
| トリガー | ThreadPool.scheduleWithFixedDelayによる定期実行 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| wlm.workload_group.mode | DISABLEDでないこと（monitor_only または enabled） |

### 実行可否判定

doRun()内でwlmModeがDISABLEDの場合は即座にreturnする。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| wlm.workload_group.mode | WlmMode | No | monitor_only | WLMの動作モード（disabled/monitor_only/enabled） |
| wlm.workload_group.enforcement_interval | long | No | 1000 | 実行間隔（ミリ秒、最小1000） |
| wlm.workload_group.duress_streak | int | No | 3 | ノード逼迫判定の連続回数閾値（最小3） |
| wlm.workload_group.node.cpu_rejection_threshold | double | No | 0.8 | CPU拒否閾値 |
| wlm.workload_group.node.cpu_cancellation_threshold | double | No | 0.9 | CPUキャンセル閾値 |
| wlm.workload_group.node.memory_rejection_threshold | double | No | 0.8 | メモリ拒否閾値 |
| wlm.workload_group.node.memory_cancellation_threshold | double | No | 0.9 | メモリキャンセル閾値 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| NodeDuressTrackers | Java API | ノードのCPU・メモリ逼迫状態 |
| ProcessProbe | Java API | プロセスCPU使用率 |
| JvmStats | Java API | JVMヒープ使用率 |
| ClusterState.metadata().workloadGroups() | Map | クラスタ上のワークロードグループ定義 |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| WorkloadGroupTaskCancellationService | Java API | タスクキャンセル実行 |
| WorkloadGroupState | Java Object | ワークロードグループ統計（拒否数、完了数等） |
| WorkloadGroupStats | Java Object | ノード統計API向けの統計情報 |

### 出力ファイル仕様

ファイル出力はなし。ノード統計APIを通じて公開される。

## 処理フロー

### 処理シーケンス

```
1. WlmModeチェック
   └─ DISABLEDの場合はスキップ
2. タスクキャンセル処理
   └─ taskCancellationService.cancelTasks()を呼び出し
   └─ nodeDuressTrackers::isNodeInDuressで逼迫判定
   └─ activeWorkloadGroupsとdeletedWorkloadGroupsを渡す
3. 削除済みワークロードグループの後処理
   └─ taskCancellationService.pruneDeletedWorkloadGroups()
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B{WlmMode == DISABLED?}
    B -->|Yes| C[スキップ]
    B -->|No| D[cancelTasks実行]
    D --> E[ノード逼迫状態を評価]
    E --> F[リソース超過ワークロードグループのタスクキャンセル]
    F --> G[削除済みワークロードグループの後処理]
    G --> H[バッチ終了]
    C --> H
```

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

本バッチはデータベースを使用しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ResourceNotFoundException | 存在しないワークロードグループIDへのアクセス | 例外スロー |
| - | OpenSearchRejectedExecutionException | リソース制限超過時のリクエスト拒否 | 呼び出し元に例外通知 |
| - | Exception | doRun()内の例外 | DEBUGログ出力してスキップ |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（次回スケジュールで再実行） |
| リトライ間隔 | enforcement_interval（デフォルト1000ms） |
| リトライ対象エラー | 全てのエラー（次回実行で自動リトライ） |

### 障害時対応

例外発生時はDEBUGログが出力され、次回スケジュールで再試行される。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | なし |
| コミットタイミング | 該当なし |
| ロールバック条件 | 該当なし |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | アクティブなワークロードグループ数とタスク数に依存 |
| 目標処理時間 | 実行間隔（1秒）内に完了すること |
| メモリ使用量上限 | ワークロードグループ状態の管理程度 |

## 排他制御

activeWorkloadGroupsはvolatile参照でクラスタ状態変更時に置換される。deletedWorkloadGroupsはHashSetで管理される。WorkloadGroupsStateAccessorを介してワークロードグループ状態の追加・削除が行われる。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| DEBUGログ | バッチ処理の例外発生時 | "Exception occurred in Workload Group service" |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| ワークロードグループ拒否数 | ノード統計APIで確認 | 運用チーム |
| タスクキャンセル数 | ノード統計APIで確認 | 運用チーム |
| ノード逼迫状態 | duress_streak連続超過 | 運用チーム |

## 備考

- @opensearch.experimentalとして実験的機能である
- SOFTモードのワークロードグループはノード逼迫時のみ拒否対象となる
- デフォルトワークロードグループ（DEFAULT_WORKLOAD_GROUP_ID）に属するタスクは拒否対象外
- SearchBackpressureServiceとの連携でshouldSBPHandle()メソッドにより処理分担を行う
- 拒否閾値と取消閾値は動的に変更可能（Dynamic設定）
