# 通知設計書 2-Async\Condition::fail

## 概要

本ドキュメントは、HH\Lib\Async\Condition クラスの fail メソッドによる非同期条件変数への失敗通知機能について記載する。

### 本通知の処理概要

Async\Condition::fail メソッドは、非同期処理における条件変数（Condition Variable）パターンを実現するための失敗通知メカニズムである。このメソッドは、待機中の非同期処理に対して処理の失敗と例外を通知する。

**業務上の目的・背景**：非同期プログラミングにおいて、処理が失敗した場合にその情報を待機中のタスクに伝達する必要がある。fail メソッドは、succeed メソッドと対になる機能として、エラー状態を通知するために使用される。これにより、待機側は try-catch ブロックで例外をキャッチし、適切なエラーハンドリングを行うことができる。

**通知の送信タイミング**：fail メソッドは、非同期処理が失敗し例外が発生した時点で呼び出される。呼び出し元が任意のタイミングで明示的に呼び出すことで通知が発生する。

**通知の受信者**：同一の Condition インスタンスに対して waitForNotificationAsync を呼び出している非同期処理が受信者となる。1つの Condition インスタンスに対しては1回のみ通知可能である。

**通知内容の概要**：Exception オブジェクトが通知内容となる。この例外は waitForNotificationAsync 内でスローされ、受信者の try-catch ブロックでキャッチされる。

**期待されるアクション**：受信者は waitForNotificationAsync から例外がスローされることを想定し、try-catch ブロックで例外をキャッチして適切なエラーハンドリング（ログ出力、リトライ、代替処理など）を行う。

## 通知種別

プログラム内非同期通知（Awaitable/ConditionWaitHandle ベース・例外通知）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（メソッド呼び出し時に即座に状態変更） |
| 優先度 | N/A（プログラム内通知のため） |
| リトライ | 無（1回のみ通知可能） |

### 送信先決定ロジック

送信先は同一 Condition インスタンスを参照する waitForNotificationAsync の呼び出し元である。インスタンスベースの1対1通知のため、明示的な送信先決定ロジックは存在しない。

## 通知テンプレート

### プログラム通知の場合

| 項目 | 内容 |
|-----|------|
| 通知形式 | Awaitable の例外完了 |
| データ型 | \Exception |
| 通知方法 | ConditionWaitHandle::fail または async ブロックによる即時例外スロー |

### 通知データ構造

```hack
// 失敗通知時のデータ
\Exception $exception  // スローされる例外オブジェクト
```

### 添付ファイル

該当なし（プログラム内通知のため）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| $exception | 通知する例外オブジェクト | 呼び出し元から引数として渡される | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | fail($exception) メソッド呼び出し | なし | 呼び出し元が明示的に失敗を通知 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 二重通知 | 同一インスタンスに対して既に succeed または fail が呼び出されている場合、invariant 違反でエラー |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[fail メソッド呼び出し] --> B{condition が null?}
    B -->|Yes| C[async ブロックで例外をスローする Awaitable を作成]
    B -->|No| D{ConditionWaitHandle?}
    D -->|Yes| E[ConditionWaitHandle::fail を呼び出し]
    D -->|No| F[invariant 違反エラー]
    C --> G[condition に Awaitable を設定]
    E --> H[待機中の処理に例外を通知]
    G --> I[終了]
    H --> I
    F --> I
```

## データベース参照・更新仕様

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

### 参照テーブル一覧

該当なし

### 更新テーブル一覧

該当なし

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| invariant 違反 | 同一インスタンスに2回以上 succeed/fail を呼び出した場合 | プログラム設計を見直し、1回のみ通知するよう修正 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（リトライ不可） |
| リトライ間隔 | N/A |
| リトライ対象エラー | なし |

## 配信設定

### レート制限

該当なし（プログラム内通知のため）

### 配信時間帯

制限なし

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

- 例外メッセージに機密情報を含めないよう注意が必要
- スタックトレースには内部実装の詳細が含まれる可能性があるため、ログ出力時は適切にマスキングを検討

## 備考

- succeed メソッドと対になる失敗通知メソッド
- waitForNotificationAsync の await 時に例外がスローされる形で受信者に通知される
- 例外の型は \Exception 基底クラスであり、任意のサブクラスを渡すことが可能

---

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

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

### 推奨読解順序

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

Condition クラスの内部状態と、通知に関わるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | Condition.php | `src/async/Condition.php` | クラスの基本構造とプロパティ |

**読解のコツ**: fail メソッドは succeed メソッドと対称的な実装になっている点に注目する。

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

fail メソッドの実装を詳細に理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Condition.php | `src/async/Condition.php` | fail メソッドの実装（41-52行目） |

**主要処理フロー**:
1. **行41-52**: fail メソッドの定義
2. **行42**: condition プロパティが null かチェック
3. **行43-45**: null の場合、async ブロックで例外をスローする Awaitable を作成
4. **行47-50**: null でない場合、ConditionWaitHandle かどうかを invariant でチェック
5. **行51**: ConditionWaitHandle の fail を呼び出し

#### Step 3: テストコードで動作を確認する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | ConditionTest.php | `tests/async/ConditionTest.php` | fail の使用例（27-37行目、50-63行目） |

**主要処理フロー**:
- **行27-37**: testFailFirst - 先に fail を呼び出すパターン
- **行50-63**: testFailLater - 後から fail を呼び出すパターン

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

```
Condition::fail($exception)
    |
    +-- [condition が null の場合]
    |       |
    |       +-- async { throw $exception; } を作成
    |       |
    |       +-- $this->condition に設定
    |
    +-- [condition が ConditionWaitHandle の場合]
            |
            +-- ConditionWaitHandle::fail($exception)
                    |
                    +-- 待機中の waitForNotificationAsync で例外スロー
```

### データフロー図

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

\Exception ─────────▶ Condition::fail() ───────▶ Awaitable 例外完了
                              |
                              v
                    ┌─────────────────┐
                    │  $condition     │
                    │  プロパティ更新  │
                    └─────────────────┘
                              |
                              v
                    waitForNotificationAsync
                    の await で例外スロー
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Condition.php | `src/async/Condition.php` | ソース | Condition クラスの実装 |
| ConditionNode.php | `src/async/ConditionNode.php` | ソース | Condition を継承したリンクリストノード |
| ConditionTest.php | `tests/async/ConditionTest.php` | テスト | Condition クラスのユニットテスト |
| BasePoll.php | `src/async/BasePoll.php` | ソース | ConditionNode を使用する Poll の基底クラス |
