# バッチ設計書 22-ResourceWatcherService

## 概要

本ドキュメントは、OpenSearchのResourceWatcherServiceが提供する3段階の頻度で動作するリソース監視バッチ処理の設計を記述する。登録されたResourceWatcherを定期的にチェックし、ファイル変更等のリソース変更を検出する汎用的なサービスである。

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

ResourceWatcherServiceは、3つの頻度レベル（HIGH: 5秒、MEDIUM: 30秒、LOW: 60秒）でResourceMonitorタスクをスケジュールし、各頻度に登録されたResourceWatcherのcheckAndNotify()メソッドを定期的に呼び出す。SSL証明書の変更監視、設定ファイルの変更監視など、様々なプラグインやモジュールがこのサービスを利用してファイルシステム上のリソース変更を検出する。

**業務上の目的・背景**：OpenSearchは動的にリソースの変更を検出する必要がある。例えば、SSL/TLS証明書ファイルの更新、設定ファイルの変更、Painlessスクリプトファイルの更新などを検出し、再起動なしに反映する必要がある。ResourceWatcherServiceはこれらの監視を統合的に管理する基盤サービスとして機能し、各コンポーネントが個別にファイル監視ロジックを実装する必要をなくす。

**バッチの実行タイミング**：ノード起動時にサービスが開始され、3つの頻度レベルそれぞれで独立したスケジュールタスクが動作する。HIGH（デフォルト5秒）、MEDIUM（デフォルト30秒）、LOW（デフォルト60秒）の3段階である。

**主要な処理内容**：
1. HIGH頻度モニターが登録済みの全ResourceWatcherに対してcheckAndNotify()を呼び出す
2. MEDIUM頻度モニターが登録済みの全ResourceWatcherに対してcheckAndNotify()を呼び出す
3. LOW頻度モニターが登録済みの全ResourceWatcherに対してcheckAndNotify()を呼び出す

**前後の処理との関連**：各モジュール（analysis-common、lang-painless、reindex、repository-s3、workload-management等）がResourceWatcherServiceにWatcherを登録し、ResourceWatcherServiceがそれらを定期的に呼び出す。

**影響範囲**：全ノード上で動作し、SSL証明書の動的リロード、設定ファイルの変更検出、各種プラグインのリソース監視に影響する。

## バッチ種別

リソース監視（ファイル変更検出）

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | HIGH: 5秒 / MEDIUM: 30秒 / LOW: 60秒（設定変更可能） |
| 実行時刻 | ノード起動後から継続的に実行 |
| 実行曜日 | 該当なし（常時） |
| 実行日 | 該当なし（常時） |
| トリガー | ThreadPool.scheduleWithFixedDelayによる定期実行 |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| resource.reload.enabled | trueである場合のみスケジュールされる（デフォルトtrue） |

### 実行可否判定

`resource.reload.enabled`がfalseの場合、スケジュールタスクは作成されず、全ての監視が無効化される。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| resource.reload.enabled | boolean | No | true | サービスの有効/無効 |
| resource.reload.interval.high | TimeValue | No | 5s | HIGH頻度の監視間隔 |
| resource.reload.interval.medium | TimeValue | No | 30s | MEDIUM頻度の監視間隔 |
| resource.reload.interval.low | TimeValue | No | 60s | LOW頻度の監視間隔 |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| 登録済みResourceWatcher | Java API | 各コンポーネントが登録したリソースウォッチャー |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| ResourceWatcherコールバック | Java API | 変更検出時にWatcherが内部処理を実行 |

### 出力ファイル仕様

ファイル出力はなし。各ResourceWatcherが検出した変更に基づいて個別に処理を行う。

## 処理フロー

### 処理シーケンス

```
1. ResourceMonitor.run()が起動（HIGH/MEDIUM/LOWそれぞれ独立）
   └─ synchronizedブロック内で実行
2. 登録済みの全ResourceWatcherに対してループ
   └─ CopyOnWriteArraySetで管理されたWatcherセット
3. 各Watcherに対してcheckAndNotify()を呼び出す
   └─ ファイルの変更有無を確認し、変更があれば通知処理を実行
4. IOException発生時はTRACEレベルでログ出力しスキップ
```

### フローチャート

```mermaid
flowchart TD
    A[モニター起動 HIGH/MEDIUM/LOW] --> B[synchronizedブロック取得]
    B --> C[登録済みWatcherリストを取得]
    C --> D{次のWatcherあり?}
    D -->|あり| E[checkAndNotify呼び出し]
    E --> F{IOException発生?}
    F -->|あり| G[TRACEログ出力]
    F -->|なし| D
    G --> D
    D -->|なし| H[モニター終了]
```

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

本バッチはデータベースを使用しない。ファイルシステム上のリソースを監視対象とする。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | IOException | ResourceWatcherのcheckAndNotify()で例外発生 | TRACEログ出力して次のWatcherへ進む |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（次回スケジュールで再試行） |
| リトライ間隔 | 各頻度の間隔（5s/30s/60s） |
| リトライ対象エラー | IOException |

### 障害時対応

個別のWatcherでの例外は他のWatcherに影響しない。サービス全体が停止した場合は、ノードの再起動が必要。

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

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

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 登録済みWatcher数に依存（通常は数件～十数件） |
| 目標処理時間 | 各頻度の間隔内に完了すること |
| メモリ使用量上限 | 軽量（Watcherのメタデータ程度） |

## 排他制御

各ResourceMonitorのrun()メソッドはsynchronizedで保護されている。3つの頻度レベルは独立したResourceMonitorインスタンスで動作するため、相互にブロックしない。ResourceWatcherのセットはCopyOnWriteArraySetで管理されており、スレッドセーフな追加・削除が可能。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| TRACEログ | Watcherのチェックで例外発生時 | "failed to check resource watcher" |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| サービス停止 | 有効設定でサービスが動作していない場合 | OpenSearchログ |

## 備考

- @PublicApi(since = "1.0.0")として公開APIである
- WatcherHandle経由でWatcherの登録解除が可能
- notifyNow()メソッドにより、スケジュール外での即座のチェックも可能
- デフォルトの登録頻度はMEDIUM（30秒）
