# 機能設計書 38-MailboxProcessor

## 概要

本ドキュメントは、F#コアライブラリにおけるMailboxProcessor（メールボックスプロセッサ）機能の機能設計を記述する。MailboxProcessorはアクターモデルに基づく並行プログラミング抽象を提供し、メッセージベースの非同期通信を実現する。

### 本機能の処理概要

**業務上の目的・背景**：マルチスレッドプログラミングにおいて、共有状態の管理は複雑でバグを生みやすい。MailboxProcessorはアクターモデルを採用し、各アクターが独自の状態を持ち、メッセージパッシングで通信することで、ロックフリーな並行プログラミングを可能にする。これにより、競合状態やデッドロックのリスクを大幅に削減できる。

**機能の利用シーン**：チャットサーバーのセッション管理、ゲームサーバーのプレイヤー状態管理、バックグラウンドワーカーの実装、イベント駆動アーキテクチャの実装、レート制限やキューイングの実装など。

**主要な処理内容**：
1. メッセージキューの管理（Mailbox内部クラス）
2. メッセージの送信（Post、PostAndReply、PostAndAsyncReply）
3. メッセージの受信（Receive、TryReceive、Scan、TryScan）
4. エラーハンドリング（Error イベント）
5. キャンセレーション対応（CancellationToken）
6. タイムアウト処理（DefaultTimeout）

**関連システム・外部連携**：.NETのAsync/Await、Task、CancellationTokenと連携。

**権限による制御**：本機能はライブラリ機能であり、権限による制御は行わない。

## 関連画面

該当なし（コアライブラリ機能であり、画面は持たない）

## 機能種別

並行処理 / メッセージパッシング / アクターモデル

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| body | MailboxProcessor<'Msg> -> Async<unit> | Yes | メッセージ処理ループ | - |
| cancellationToken | CancellationToken | No | キャンセルトークン | - |
| timeout | int | No | タイムアウト（ミリ秒） | 負の値は無限待機 |
| message | 'Msg | Yes | 送信するメッセージ | - |
| buildMessage | AsyncReplyChannel<'Reply> -> 'Msg | No | 返信付きメッセージ構築関数 | - |
| scanner | 'Msg -> Async<'T> option | No | メッセージスキャン関数 | - |

### 入力データソース

F#プログラム内で生成されるメッセージ値。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| 結果 | unit / 'Msg / 'Msg option / 'Reply / 'Reply option / Async<'Reply> | 各操作に応じた戻り値 |

### 出力先

関数の戻り値またはイベントとしてプログラムに返却。

## 処理フロー

### 処理シーケンス

```
1. MailboxProcessor生成
   └─ body関数とキャンセルトークンを受け取る
2. Start/StartImmediateで処理開始
   └─ body関数がasync{}ブロックとして実行開始
3. メッセージループ
   └─ Receive/Scan等でメッセージを待機
   └─ メッセージ到着時に処理を実行
   └─ 状態を更新して次のメッセージを待機
4. 外部からのPost
   └─ メッセージをキューに追加
   └─ 待機中のReceiveを再開
```

### フローチャート

```mermaid
flowchart TD
    A[MailboxProcessor.Start] --> B[body関数実行開始]
    B --> C{Receive待機}
    C -->|メッセージあり| D[メッセージ処理]
    D --> E[状態更新]
    E --> C
    C -->|タイムアウト| F[TimeoutException]

    G[外部: Post] --> H[キューに追加]
    H --> I[待機解除]
    I --> C

    J[外部: PostAndReply] --> K[ReplyChannel付きメッセージ生成]
    K --> H
    D -->|Reply| L[結果を返却]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-38-1 | シングルリーダー | 1つのMailboxProcessorには1つのリーダーのみ許可 | 常に |
| BR-38-2 | FIFO順序 | メッセージはFIFO順序で処理される | 通常のReceive |
| BR-38-3 | Scan選択 | Scanは条件に合うメッセージを優先的に取得可能 | Scan使用時 |
| BR-38-4 | 例外伝播 | body内の例外はErrorイベントに伝播 | 例外発生時 |

### 計算ロジック

- メッセージキューはQueue<'Msg>で実装（FIFO）
- Scanはinboxリストをスキャンして条件に合うメッセージを探索

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

該当なし（メモリ上のデータ操作のみ）

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| TimeoutException | 実行時例外 | Receive/PostAndReplyがタイムアウトした場合 | TryReceive/TryPostAndReplyを使用 |
| InvalidOperationException | 実行時例外 | 既に開始済みのMailboxProcessorを再度Startした場合 | 新しいインスタンスを作成 |
| ObjectDisposedException | 実行時例外 | Dispose済みのMailboxProcessorにPostした場合 | isThrowExceptionAfterDisposedフラグで制御可能 |

### リトライ仕様

該当なし（アプリケーション層で実装）

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

該当なし（メッセージパッシングモデル）

## パフォーマンス要件

- Post操作はロックを取得するがO(1)
- Receive操作はメッセージ待機中にスレッドをブロックしない（async）
- Scan操作はinboxサイズに比例（O(n)）

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

特になし（メモリ内通信のみ）

## 備考

- MailboxProcessorはErlangのアクターモデルに影響を受けている
- 1つのMailboxProcessorは1つの論理スレッドとして動作
- IDisposableを実装しており、リソースクリーンアップが可能

---

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

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

### 推奨読解順序

#### Step 1: 内部Mailbox型を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | mailbox.fs | `src/FSharp.Core/mailbox.fs` | Mailbox<'Msg>型の定義（61-348行目） |

**読解のコツ**:
- `arrivals`: 到着メッセージのキュー（Queue<'Msg>）
- `inbox`: スキャン中に一時保存されるメッセージリスト（List<'Msg>）
- `savedCont`: 待機中の継続（再開用コールバック）
- `pulse`: タイムアウト/キャンセル用のAutoResetEvent

**主要処理フロー**:
1. **63-67行目**: 内部状態の初期化（arrivals、inbox、savedCont、pulse）
2. **116-123行目**: `CurrentQueueLength` - キュー長の取得
3. **125-139行目**: `ScanArrivals` - 到着キューのスキャン
4. **156-174行目**: `ReceiveFromArrivals` / `ReceiveFromInbox` - メッセージ取得
5. **176-197行目**: `Post` - メッセージ送信とリーダー再開

#### Step 2: MailboxProcessor型を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | mailbox.fs | `src/FSharp.Core/mailbox.fs` | MailboxProcessor<'Msg>型の定義（353-549行目） |

**主要処理フロー**:
1. **362-372行目**: コンストラクタ - body、cancellationToken、defaultTimeoutの設定
2. **395-409行目**: `PrepareToStart` / `Start` - 処理開始
3. **411-417行目**: `StartImmediate` - 即時開始（スレッドプール不使用）
4. **419-420行目**: `Post` - ファイアアンドフォーゲット送信
5. **422-440行目**: `PostAndReply` / `TryPostAndReply` - 同期的な返信待ち
6. **442-501行目**: `PostAndAsyncReply` / `PostAndTryAsyncReply` - 非同期返信待ち
7. **503-513行目**: `Receive` / `TryReceive` - メッセージ受信
8. **515-520行目**: `Scan` / `TryScan` - 条件付きメッセージ受信

#### Step 3: AsyncReplyChannel型を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | mailbox.fs | `src/FSharp.Core/mailbox.fs` | AsyncReplyChannel<'Reply>型（353-357行目） |

**読解のコツ**:
- 返信用のワンショットチャネル
- `Reply`メソッドを呼ぶとResultCellに結果を格納
- PostAndReply側はResultCellの結果を待機

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

```
ユーザーコード
    │
    ├─ MailboxProcessor.Start(body)
    │      └─ PrepareToStart() - 開始準備
    │             └─ Async.Start(body self) - 非同期実行開始
    │
    ├─ mbp.Post(message)
    │      └─ mailbox.Post(message)
    │             ├─ arrivals.Enqueue(message)
    │             └─ savedCont.action() / pulse.Set() - リーダー再開
    │
    ├─ mbp.Receive()
    │      └─ mailbox.Receive(timeout)
    │             └─ ReceiveFromInbox() -> ReceiveFromArrivals()
    │                    └─ メッセージ取得 or waitOne()
    │
    └─ mbp.PostAndReply(fun ch -> Message(ch))
           └─ ResultCell.RegisterResult()
                  └─ TryWaitForResultSynchronously(timeout)
```

### データフロー図

```
[送信側]                      [MailboxProcessor]                  [受信側(body)]

Post(msg) ───────────────▶ arrivals.Enqueue(msg) ────────────▶ Receive()
                                   │                              │
                                   └─── savedCont再開 ────────────┘

PostAndReply ────────────▶ arrivals.Enqueue(msg+channel) ────▶ Receive()
    │                                                              │
    │                                                              ▼
    │                                                         channel.Reply(result)
    │                                                              │
    ◀───────────────────── ResultCell.Result ◀────────────────────┘

```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| mailbox.fs | `src/FSharp.Core/mailbox.fs` | ソース | MailboxProcessor/Mailbox型の実装 |
| mailbox.fsi | `src/FSharp.Core/mailbox.fsi` | シグネチャ | MailboxProcessor型のシグネチャ定義 |
| async.fs | `src/FSharp.Core/async.fs` | ソース | Asyncワークフロー（依存） |
