# 通知設計書 11-QUICセッション通知

## 概要

本ドキュメントは、Node.jsのQUICプロトコル実装における診断チャンネルを利用したセッション関連イベント通知機構の設計を記述する。QUICプロトコルのエンドポイント、セッション、ストリームに関する各種イベントを`diagnostics_channel`を通じて購読者に通知する仕組みを定義する。

### 本通知の処理概要

QUICセッション通知は、Node.jsの実験的なQUICプロトコル実装において、セッションのライフサイクルやデータ転送に関するイベントを診断チャンネル経由で外部に通知する機能である。

**業務上の目的・背景**：QUICプロトコルはHTTP/3の基盤となる次世代トランスポートプロトコルであり、低遅延・高信頼性の通信を実現する。開発者やシステム管理者がQUIC接続の状態を監視・デバッグするためには、セッションの作成・終了、データグラムの送受信、ハンドシェイクの完了など各種イベントをリアルタイムで把握する必要がある。本通知機構はこれらの要件に対応し、アプリケーション層での監視・ログ収集・トレーシングを可能にする。

**通知の送信タイミング**：以下のイベント発生時に診断チャンネルへ通知が送信される：
- エンドポイント：作成時、リスニング開始時、クローズ中、クローズ完了時、エラー発生時、ビジー状態変更時
- セッション：クライアント/サーバーセッション作成時、ストリーム開始/受信時、データグラム送受信時、キー更新時、クローズ中/完了時、パス検証時、セッションチケット受信時、バージョンネゴシエーション時、ハンドシェイク完了時

**通知の受信者**：`diagnostics_channel`のsubscribe()メソッドを使用して各チャンネルを購読している任意のモジュールやアプリケーションコードが受信者となる。APM（Application Performance Monitoring）ツール、ログ収集システム、カスタム監視スクリプトなどが想定される。

**通知内容の概要**：各イベントに応じたコンテキスト情報（エンドポイント、セッション、ストリームオブジェクト、エラー情報、アドレス情報など）がオブジェクト形式で通知される。

**期待されるアクション**：受信者は通知内容に基づき、ログ記録、メトリクス収集、アラート発火、トレース情報の伝播などを行うことが期待される。

## 通知種別

内部イベント通知（diagnostics_channel）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（Pub/Sub） |
| 優先度 | 高（リアルタイム性重視） |
| リトライ | なし（購読者がいない場合は通知破棄） |

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

`diagnostics_channel`の`channel()`メソッドで取得したチャンネルオブジェクトに対して`subscribe()`メソッドを呼び出した全ての購読者に通知が送信される。購読者の登録は動的に行われ、`hasSubscribers`プロパティがtrueの場合のみ通知処理が実行される。

## 通知テンプレート

### チャンネル名一覧

#### エンドポイント関連チャンネル

| チャンネル名 | 説明 |
|-------------|------|
| `quic.endpoint.created` | エンドポイント作成時 |
| `quic.endpoint.listen` | エンドポイントがリスニング開始時 |
| `quic.endpoint.closing` | エンドポイントがクローズ処理中 |
| `quic.endpoint.closed` | エンドポイントがクローズ完了時 |
| `quic.endpoint.error` | エンドポイントでエラー発生時 |
| `quic.endpoint.busy.change` | エンドポイントのビジー状態変更時 |
| `quic.session.created.client` | クライアントセッション作成時 |
| `quic.session.created.server` | サーバーセッション作成時 |

#### セッション関連チャンネル

| チャンネル名 | 説明 |
|-------------|------|
| `quic.session.open.stream` | セッションでストリーム開始時 |
| `quic.session.received.stream` | セッションでストリーム受信時 |
| `quic.session.send.datagram` | セッションでデータグラム送信時 |
| `quic.session.update.key` | セッションでキー更新時 |
| `quic.session.closing` | セッションがクローズ処理中 |
| `quic.session.closed` | セッションがクローズ完了時 |
| `quic.session.receive.datagram` | セッションでデータグラム受信時 |
| `quic.session.receive.datagram.status` | データグラム受信ステータス通知時 |
| `quic.session.path.validation` | パス検証完了時 |
| `quic.session.ticket` | セッションチケット受信時 |
| `quic.session.version.negotiation` | バージョンネゴシエーション時 |
| `quic.session.handshake` | ハンドシェイク完了時 |

### 本文テンプレート

各チャンネルの通知ペイロードは以下の構造を持つ：

#### quic.endpoint.created
```javascript
{
  endpoint: QuicEndpoint,  // エンドポイントオブジェクト
  config: Object           // 設定オプション
}
```

#### quic.session.handshake
```javascript
{
  session: QuicSession,
  local: SocketAddress,
  remote: SocketAddress,
  servername: string,
  protocol: string,
  cipher: string,
  cipherVersion: string,
  validationErrorReason: string,
  validationErrorCode: number
}
```

### 添付ファイル

該当なし（内部イベント通知のため）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| endpoint | エンドポイントオブジェクト | QuicEndpoint インスタンス | Yes |
| session | セッションオブジェクト | QuicSession インスタンス | Yes（セッション関連イベント） |
| stream | ストリームオブジェクト | QuicStream インスタンス | Yes（ストリーム関連イベント） |
| error | エラー情報 | Error オブジェクト | No |
| address | ソケットアドレス | SocketAddress インスタンス | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 内部イベント | QuicEndpoint作成 | hasSubscribers == true | エンドポイントのコンストラクタ完了時 |
| 内部イベント | listen()呼び出し | hasSubscribers == true | リスニング状態への遷移時 |
| 内部イベント | connect()呼び出し | hasSubscribers == true | クライアント接続時 |
| 内部イベント | セッションハンドシェイク完了 | hasSubscribers == true | TLSハンドシェイク成功時 |
| 内部イベント | ストリーム作成/受信 | hasSubscribers == true | createBidirectionalStream等の呼び出し時 |
| 内部イベント | データグラム送受信 | hasSubscribers == true | sendDatagram呼び出し時、データグラム受信時 |
| 内部イベント | close()呼び出し | hasSubscribers == true | グレースフルクローズ開始時 |
| 内部イベント | destroy()呼び出し | hasSubscribers == true | 強制終了時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| hasSubscribers == false | 購読者がいない場合は通知処理をスキップ |
| セッション/エンドポイントがdestroyed | 既に破棄されたオブジェクトからは通知しない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[イベント発生] --> B{hasSubscribers?}
    B -->|false| C[処理スキップ]
    B -->|true| D[通知データ構築]
    D --> E[channel.publish実行]
    E --> F[各購読者のコールバック呼び出し]
    F --> G{コールバックでエラー?}
    G -->|Yes| H[nextTickでuncaughtException発火]
    G -->|No| I[正常終了]
    H --> I
    C --> I
```

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

### 参照テーブル一覧

該当なし（メモリ内オブジェクトのみ使用）

### 更新テーブル一覧

該当なし（メモリ内オブジェクトのみ使用）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 購読者コールバックエラー | 購読者の処理で例外発生 | `process.nextTick`で`triggerUncaughtException`を呼び出し |
| セッション破棄後アクセス | destroyed状態でのメソッド呼び出し | ERR_INVALID_STATE例外をスロー |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | 該当なし |
| リトライ対象エラー | 該当なし（Pub/Subモデルのためリトライなし） |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（イベント発生に応じて即座に通知） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（24時間リアルタイム通知）

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

- セッション情報にはTLS暗号化に関する情報（cipher, cipherVersion）が含まれるため、ログ出力時は機密情報の取り扱いに注意
- セッションチケットは再接続時の認証に使用されるため、外部への露出を避ける
- 診断チャンネルは同一プロセス内でのみ利用可能であり、プロセス間での情報漏洩リスクは低い

## 備考

- QUICは`--experimental-quic`フラグを有効にした場合のみ利用可能
- Node.jsがcryptoサポート付きでコンパイルされている必要がある
- 本機能は実験的機能であり、APIは将来変更される可能性がある

---

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

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

### 推奨読解順序

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

QUICの通知で使用されるデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | symbols.js | `lib/internal/quic/symbols.js` | 内部シンボル定義を確認。kOwner, kFinishClose, kDatagram等のシンボルがQUICオブジェクト間の連携に使用される |
| 1-2 | state.js | `lib/internal/quic/state.js` | QuicEndpointState, QuicSessionState, QuicStreamStateの3つの状態管理クラス。C++層とのデータ共有にDataViewを使用 |
| 1-3 | stats.js | `lib/internal/quic/stats.js` | QuicEndpointStats, QuicSessionStats, QuicStreamStatsの統計情報クラス。BigUint64Arrayでパフォーマンス統計を管理 |

**読解のコツ**: DataViewとBigUint64Arrayを使用したC++/JS間のゼロコピーデータ共有パターンに注目。IDX_STATE_*定数がバッファ内のオフセットを定義している。

#### Step 2: diagnostics_channelの基本を理解する

通知基盤となるdiagnostics_channelの仕組みを把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | diagnostics_channel.js | `lib/diagnostics_channel.js` | Channelクラスのpublish()メソッドが通知の実体。ActiveChannelとChannelの2つのプロトタイプを動的に切り替える最適化に注目 |

**主要処理フロー**:
1. **行181-223**: Channelクラスの定義。購読者がいない場合の軽量実装
2. **行105-179**: ActiveChannelクラス。購読者がいる場合のアクティブな実装
3. **行151-162**: publish()メソッドの実装。購読者のコールバックを順次呼び出し、エラーは`triggerUncaughtException`で処理

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

QUIC機能のメインエントリーポイントを確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | quic.js | `lib/internal/quic/quic.js` | メインのQUIC実装ファイル。診断チャンネルの定義と使用箇所を確認 |

**主要処理フロー**:
- **行164-184**: 20個の診断チャンネル定義
- **行1748-1762**: QuicEndpointコンストラクタでの`onEndpointCreatedChannel.publish()`
- **行1224-1230**: sendDatagram()での`onSessionSendDatagramChannel.publish()`
- **行1535-1540**: ハンドシェイク完了時の`onSessionHandshakeChannel.publish()`

#### Step 4: 各通知の実装箇所を理解する

診断チャンネルが実際に使用される箇所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | quic.js | `lib/internal/quic/quic.js` | 行1160-1166のonSessionOpenStreamChannel、行1424-1430のonSessionReceiveDatagramChannelなど各publish呼び出し箇所 |

**主要処理フロー**:
- **行1754-1758**: エンドポイント作成通知
- **行1801-1806**: ビジー状態変更通知
- **行2008-2013**: エンドポイントエラー通知
- **行1361-1366**: セッションクローズ通知

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

```
quic.js (エントリーポイント)
    │
    ├─ QuicEndpoint (クラス)
    │      ├─ constructor() → onEndpointCreatedChannel.publish()
    │      ├─ [kListen]() → onEndpointListeningChannel.publish()
    │      ├─ [kConnect]() → onEndpointClientSessionChannel.publish()
    │      ├─ close() → onEndpointClosingChannel.publish()
    │      ├─ busy (setter) → onEndpointBusyChangeChannel.publish()
    │      ├─ [kFinishClose]() → onEndpointClosedChannel.publish()
    │      │                   → onEndpointErrorChannel.publish()
    │      └─ [kNewSession]() → onEndpointServerSessionChannel.publish()
    │
    ├─ QuicSession (クラス)
    │      ├─ #createStream() → onSessionOpenStreamChannel.publish()
    │      ├─ sendDatagram() → onSessionSendDatagramChannel.publish()
    │      ├─ updateKey() → onSessionUpdateKeyChannel.publish()
    │      ├─ close() → onSessionClosingChannel.publish()
    │      ├─ destroy() → onSessionClosedChannel.publish()
    │      ├─ [kDatagram]() → onSessionReceiveDatagramChannel.publish()
    │      ├─ [kDatagramStatus]() → onSessionReceiveDatagramStatusChannel.publish()
    │      ├─ [kPathValidation]() → onSessionPathValidationChannel.publish()
    │      ├─ [kSessionTicket]() → onSessionTicketChannel.publish()
    │      ├─ [kVersionNegotiation]() → onSessionVersionNegotiationChannel.publish()
    │      ├─ [kHandshake]() → onSessionHandshakeChannel.publish()
    │      └─ [kNewStream]() → onSessionReceivedStreamChannel.publish()
    │
    └─ diagnostics_channel.js
           └─ Channel.publish() → 購読者コールバック呼び出し
```

### データフロー図

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

QUICイベント発生          diagnostics_channel                   購読者
(セッション作成等)
        │                         │                                 │
        ▼                         ▼                                 ▼
┌─────────────────┐      ┌─────────────────┐              ┌─────────────────┐
│ QuicEndpoint    │      │ Channel         │              │ APMツール       │
│ QuicSession     │ ───▶ │ .publish()      │ ───────────▶ │ ログ収集       │
│ QuicStream      │      │                 │              │ 監視システム   │
└─────────────────┘      └─────────────────┘              └─────────────────┘
        │                         │                                 │
        │                         ▼                                 │
        │                 hasSubscribers?                          │
        │                    │      │                               │
        │               Yes ─┘      └─ No                          │
        │                │               │                          │
        │                ▼               ▼                          │
        │         コールバック実行  処理スキップ                    │
        │                │                                          │
        └────────────────┴──────────────────────────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| quic.js | `lib/internal/quic/quic.js` | ソース | QUIC機能のメイン実装。診断チャンネルの定義と通知送信を実装 |
| state.js | `lib/internal/quic/state.js` | ソース | QuicEndpointState, QuicSessionState, QuicStreamStateの状態管理クラス |
| stats.js | `lib/internal/quic/stats.js` | ソース | QuicEndpointStats, QuicSessionStats, QuicStreamStatsの統計情報クラス |
| symbols.js | `lib/internal/quic/symbols.js` | ソース | 内部シンボル定義（kOwner, kFinishClose等） |
| diagnostics_channel.js | `lib/diagnostics_channel.js` | ソース | 診断チャンネルの基盤実装。Channel/ActiveChannelクラス |
