# 機能設計書 5-LowPri

## 概要

本ドキュメントは、Hack Standard Library (HSL) の非同期処理モジュール `HH\Lib\Async\LowPri` クラスの機能設計書である。

### 本機能の処理概要

**業務上の目的・背景**：
非同期プログラミングでは、クリティカルパス上の処理と、バックグラウンドで実行しても良い処理が混在することがある。例えば、ユーザーへのレスポンスを優先しつつ、ログ記録やキャッシュの事前読み込みなどをバックグラウンドで実行したい場合がある。`LowPri`クラスは、ASIOの優先度メカニズムを活用し、非同期ラムダを低優先度コンテキストで実行するラッパーを提供する。低優先度で開始した処理は、他の高優先度の処理がない時（例：IO待ち時）にのみ実行され、必要に応じて`prioritize()`で優先度を上げることができる。

**機能の利用シーン**：
- クリティカルパスをブロックしたくない事前計算や事前読み込み
- レスポンス返却後に実行しても良いログ記録や監査処理
- 投機的な処理開始で、結果が必要になった時点で優先度を上げる場合
- バックグラウンドでのキャッシュウォームアップ

**主要な処理内容**：
1. `LowPri<T>`インスタンスを作成
2. `run()`メソッドで非同期ラムダを低優先度コンテキストで実行開始
3. 低優先度処理は高優先度処理がない時のみ実行される
4. `prioritize()`メソッドで優先度を通常に引き上げ可能
5. `await`で結果を取得

**関連システム・外部連携**：
- HHVMの`PriorityBridgeWaitHandle`を使用して優先度の橋渡し
- `<<__AsioLowPri>>`属性で低優先度コンテキストを指定

**権限による制御**：該当なし（ライブラリ機能のため）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | 画面なし | - | 本プロジェクトはUIを持たないライブラリのため該当なし |

## 機能種別

非同期優先度制御 / バックグラウンド処理

## 入力仕様

### 入力パラメータ

#### run()メソッド

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| action | (function()[_]: Awaitable&lt;T&gt;) | Yes | 低優先度で実行する非同期ラムダ | callable |

### 入力データソース

- プログラムから直接呼び出し（API）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| run()戻り値 | Awaitable&lt;T&gt; | 実行結果を含むAwaitable |

### 出力先

- 呼び出し元プログラムへの戻り値

## 処理フロー

### 処理シーケンス

```
1. new LowPri<T>()でインスタンス作成
   └─ $wh = null, $isPrioritized = false で初期化
2. run($action)で実行開始
   └─ 同一インスタンスでの2回目の呼び出しはinvariant違反
   └─ lowpri()静的メソッドで低優先度コンテキストを作成
   └─ PriorityBridgeWaitHandle::createで優先度橋渡し
   └─ 事前にprioritize()が呼ばれていた場合、即座に優先度を上げる
3. 低優先度で$actionを実行
   └─ 高優先度処理がない時のみ実行が進む
4. （オプション）prioritize()で優先度を上げる
   └─ $isPrioritizedをtrueに設定
   └─ $whが存在すれば$wh->prioritize()を呼び出し
5. await $resultで結果を取得
```

### フローチャート

```mermaid
flowchart TD
    A[new LowPri] --> B[run開始]
    B --> C{$wh is null?}
    C -->|No| D[InvariantException]
    C -->|Yes| E[lowpri で低優先度async作成]
    E --> F[PriorityBridgeWaitHandle::create]
    F --> G{$isPrioritized?}
    G -->|Yes| H[$wh->prioritize]
    G -->|No| I[低優先度で実行開始]
    H --> I
    I --> J{prioritize呼び出し?}
    J -->|Yes| K[$isPrioritized = true]
    K --> L[$wh->prioritize]
    L --> M[通常優先度で継続実行]
    J -->|No| N[低優先度で継続]
    M --> O[結果を返却]
    N --> O
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-01 | 単一実行 | run()は同一インスタンスで1回のみ呼び出し可能 | 常時 |
| BR-02 | 低優先度実行 | 処理は高優先度処理がない時のみ実行される | prioritize()未呼び出し時 |
| BR-03 | 事前prioritize | run()前にprioritize()を呼ぶと、実行開始時から通常優先度 | prioritize()がrun()より先 |
| BR-04 | 事後prioritize | run()後にprioritize()を呼ぶと、その時点から通常優先度 | prioritize()がrun()より後 |
| BR-05 | 結果の型保持 | 型パラメータTで指定した型の結果が返却される | 常時 |

### 計算ロジック

**優先度状態遷移**：
```
初期状態: $wh = null, $isPrioritized = false
    |
    +-- [run()前にprioritize()]
    |       $isPrioritized = true
    |       |
    |       +-- [run()]
    |               $wh = PriorityBridgeWaitHandle::create(...)
    |               $wh->prioritize()  // 即座に優先度上げ
    |
    +-- [run()呼び出し]
            $wh = PriorityBridgeWaitHandle::create(...)
            // 低優先度で開始
            |
            +-- [後からprioritize()]
                    $isPrioritized = true
                    $wh->prioritize()  // この時点で優先度上げ
```

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

該当なし（メモリ上での状態管理のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| InvariantException | 実行時エラー | run()を2回呼び出した | 新しいLowPriインスタンスを作成する |
| Exception | ユーザー例外 | $action内で例外発生 | 呼び出し元でcatchして処理 |

### リトライ仕様

本機能自体にリトライ機構は組み込まれていない。

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

該当なし

## パフォーマンス要件

- 低優先度処理はI/O待機フェーズでのみ実行されるため、クリティカルパスに影響を与えない
- prioritize()の呼び出しは軽量で、即座に優先度変更が反映される
- PriorityBridgeWaitHandleのオーバーヘッドは最小限

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

該当なし（ライブラリ内部機能のため）

## 備考

- `<<__AsioLowPri>>`属性はHHVM固有の機能
- `PriorityBridgeWaitHandle`は優先度の異なるコンテキスト間を橋渡しする
- `[ctx $action, write_props]`はコンテキストと書き込みプロパティの修飾子
- LowPriインスタンスは使い捨て（1回のrun()のみ対応）

---

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

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

### 推奨読解順序

#### Step 1: クラス構造とプロパティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | LowPri.php | `src/async/LowPri.php` | クラス定義とプロパティ（26-33行目） |

**読解のコツ**: `LowPri<T>`は型パラメータを1つ持ち、これが処理結果の型となる。

**主要なプロパティ**:
- **29行目**: `private ?PriorityBridgeWaitHandle<T> $wh` - 優先度橋渡しハンドル
- **33行目**: `private bool $isPrioritized` - 優先度上げフラグ

#### Step 2: 低優先度コンテキストの作成を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | LowPri.php | `src/async/LowPri.php` | lowpri()静的メソッド（35-40行目） |

**主要処理フロー**:
- **35行目**: `<<__AsioLowPri>>` - 低優先度コンテキスト属性
- **36-39行目**: 引数のactionを実行して結果を返す

#### Step 3: run()メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | LowPri.php | `src/async/LowPri.php` | run()メソッド（52-63行目） |

**主要処理フロー**:
- **55行目**: `invariant($this->wh is null, ...)` - 2回呼び出し防止
- **57行目**: `self::lowpri($action)` - 低優先度コンテキストで実行
- **58行目**: `PriorityBridgeWaitHandle::create($child)` - 優先度橋渡し作成
- **59-61行目**: 事前prioritizeチェックと適用
- **62行目**: `await $this->wh` - 結果を待機して返却

#### Step 4: prioritize()メソッドを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | LowPri.php | `src/async/LowPri.php` | prioritize()メソッド（74-77行目） |

**主要処理フロー**:
- **75行目**: `$this->isPrioritized = true` - フラグ設定
- **76行目**: `$this->wh?->prioritize()` - 既存WHがあれば優先度上げ

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

```
new LowPri<T>()
    |
    +-- プロパティ初期化
            $wh = null
            $isPrioritized = false

LowPri::run($action)
    |
    +-- invariant: $wh is null
    |
    +-- LowPri::lowpri($action)  [<<__AsioLowPri>>]
    |       |
    |       +-- await $action()
    |
    +-- PriorityBridgeWaitHandle::create($child)
    |       |
    |       +-- $this->wh に設定
    |
    +-- [条件: $isPrioritized]
    |       |
    |       +-- $this->wh->prioritize()
    |
    +-- await $this->wh
            |
            +-- 結果を返却

LowPri::prioritize()
    |
    +-- $isPrioritized = true
    +-- $this->wh?->prioritize()
```

### データフロー図

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

(function(): Awaitable<T>)
        |
        v
    LowPri::run()
        |
        v
    ┌─────────────────────────────────────────────────────────┐
    │ <<__AsioLowPri>>                                        │
    │ lowpri($action)                                         │
    │   - 低優先度コンテキストで$action()を実行               │
    └─────────────────────────────────────────────────────────┘
        |
        v
    ┌─────────────────────────────────────────────────────────┐
    │ PriorityBridgeWaitHandle                                │
    │   - 低優先度→通常優先度の橋渡し                         │
    │   - prioritize()で優先度を引き上げ可能                  │
    └─────────────────────────────────────────────────────────┘
        |
        v
    await $wh
        |
        v
    Awaitable<T> ──────────> T (結果)
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| LowPri.php | `src/async/LowPri.php` | ソース | LowPriクラスの実装 |
| LowPriTest.php | `tests/async/LowPriTest.php` | テスト | LowPriの単体テスト |
| Poll.php | `src/async/Poll.php` | ソース | LowPriと組み合わせて使用可能（テスト参照） |
