# 通知設計書 8-ネットワーク接続通知

## 概要

本ドキュメントは、Node.jsのnetモジュールにおける診断チャンネル通知機能の設計書である。

### 本通知の処理概要

ネットワーク接続通知は、Node.jsアプリケーションがTCP/IPCソケット接続を行う際、およびサーバーがリッスン状態になる際に診断チャンネルに通知を送信する機能を提供する。これにより、ネットワーク接続の状態を外部から監視・計装することが可能となる。

**業務上の目的・背景**：分散システムにおいて、ネットワーク接続の監視は重要である。クライアントからの接続、サーバーへの接続、リッスン開始などのイベントを追跡することで、接続障害の早期検出、接続数の監視、パフォーマンス分析が可能となる。ネットワーク接続通知は、アプリケーションコードを変更せずにこれらの情報を収集する標準的な方法を提供する。

**通知の送信タイミング**：
- net.client.socket: クライアントソケット接続開始時
- net.server.socket: サーバーがクライアント接続を受け入れた時
- net.server.listen (TracingChannel): サーバーリッスン開始/完了/エラー時

**通知の受信者**：各診断チャンネルに対してsubscribe()で登録したコールバック関数。APMツール、トレーシングライブラリ、カスタム監視コードなどが想定される。

**通知内容の概要**：ソケットオブジェクト、サーバーインスタンス、オプション、エラー情報など。

**期待されるアクション**：購読者は受信したデータを使用して、接続のトレーシング、メトリクス収集、ログ出力などを行う。

## 通知種別

内部イベント通知（diagnostics_channel）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高（接続イベントはリアルタイム性が重要） |
| リトライ | なし（同期実行のため） |

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

各チャンネルに対してsubscribe()を呼び出した購読者に送信される。hasSubscribersで事前チェックを行い、購読者がいない場合はpublish()をスキップしてパフォーマンスオーバーヘッドを最小化。

## 通知テンプレート

### チャンネル一覧

| チャンネル名 | タイミング | 説明 |
|-------------|---------|------|
| net.client.socket | クライアント接続開始時 | Socket.connect()呼び出し時に発火 |
| net.server.socket | サーバー接続受け入れ時 | connectionイベント発火後に発火 |
| tracing:net.server.listen:asyncStart | リッスン開始時 | Server.listen()呼び出し時に発火 |
| tracing:net.server.listen:asyncEnd | リッスン完了時 | リッスン成功時に発火 |
| tracing:net.server.listen:error | リッスンエラー時 | リッスン失敗時に発火 |

### データ構造

```javascript
// net.client.socket
{
  socket: Socket  // クライアントソケットオブジェクト
}

// net.server.socket
{
  socket: Socket  // サーバー側のソケットオブジェクト
}

// tracing:net.server.listen:asyncStart
{
  server: Server,  // サーバーインスタンス
  options: Object  // リッスンオプション
}

// tracing:net.server.listen:asyncEnd
{
  server: Server  // サーバーインスタンス
}

// tracing:net.server.listen:error
{
  server: Server,  // サーバーインスタンス
  error: Error     // エラーオブジェクト
}
```

### 添付ファイル

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

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| socket | ソケットオブジェクト | Socketインスタンス | Yes（client/server.socket） |
| server | サーバーインスタンス | Serverインスタンス | Yes（listen関連） |
| options | リッスンオプション | listen()引数 | 一部 |
| error | エラーオブジェクト | UVExceptionWithHostPort | 一部 |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| クライアント接続 | Socket.connect() | hasSubscribers == true | 接続開始時 |
| サーバー接続受け入れ | onconnection() | hasSubscribers == true | connectionイベント発火後 |
| リッスン開始 | Server.listen() | hasSubscribers == true | リッスン処理開始時 |
| リッスン完了 | setupListenHandle() | hasSubscribers == true | リッスン成功時 |
| リッスンエラー | setupListenHandle() | hasSubscribers == true | リッスン失敗時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 購読者なし | hasSubscribersがfalseの場合、publish()をスキップ |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    subgraph クライアント側
        A[net.connect呼び出し] --> B[new Socket]
        B --> C[Socket.connect呼び出し]
        C --> D{hasSubscribers?}
        D -->|Yes| E[net.client.socket発火]
        D -->|No| F[スキップ]
        E --> G[接続処理続行]
        F --> G
    end

    subgraph サーバー側
        H[Server.listen呼び出し] --> I{hasSubscribers?}
        I -->|Yes| J[net.server.listen:asyncStart発火]
        I -->|No| K[スキップ]
        J --> L[setupListenHandle]
        K --> L
        L --> M{結果}
        M -->|成功| N{hasSubscribers?}
        N -->|Yes| O[net.server.listen:asyncEnd発火]
        N -->|No| P[スキップ]
        M -->|エラー| Q{hasSubscribers?}
        Q -->|Yes| R[net.server.listen:error発火]
        Q -->|No| S[スキップ]
    end

    subgraph 接続受け入れ
        T[クライアント接続] --> U[onconnection]
        U --> V[connectionイベント発火]
        V --> W{hasSubscribers?}
        W -->|Yes| X[net.server.socket発火]
        W -->|No| Y[スキップ]
    end
```

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

### 参照テーブル一覧

本通知はデータベースを使用しない。

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | - | メモリ内オブジェクトのみ使用 |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | データベース更新なし |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| アドレス使用中 | EADDRINUSE | net.server.listen:errorで通知後、errorイベント発火 |
| 権限エラー | EACCES | net.server.listen:errorで通知後、errorイベント発火 |
| 接続拒否 | ECONNREFUSED | net.client.socketは接続開始時点で発火済み、その後errorイベント |
| タイムアウト | 接続タイムアウト | net.client.socketは接続開始時点で発火済み |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（通知自体にはリトライなし） |
| リトライ間隔 | なし |
| リトライ対象エラー | なし |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | なし（制限なし） |
| 1日あたり上限 | なし |

### 配信時間帯

制限なし（プログラム実行中は常時利用可能）

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

- ソケットオブジェクトにはリモートアドレス情報が含まれるため、ログ出力時には注意が必要
- 接続先情報（ホスト名、ポート番号）の取り扱いに注意
- 購読者のパフォーマンスがネットワーク接続全体のパフォーマンスに影響するため、軽量な処理を心がける

## 備考

- Node.js v18.8.0でnet.client.socket/net.server.socketが追加
- Node.js v18.17.0でnet.server.listen（TracingChannel）が追加
- hasSubscribersチェックにより、購読者がいない場合のオーバーヘッドは最小限
- net.server.listenはTracingChannelを使用しているため、start/end/asyncStart/asyncEnd/errorの5つのサブチャンネルが利用可能（ただし実際に使用されているのはasyncStart/asyncEnd/error）
- クラスタモードでは、ワーカープロセスでもこれらの通知が発火する

---

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

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

### 推奨読解順序

#### Step 1: チャンネル定義を理解する

まず、診断チャンネルの定義箇所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | net.js | `lib/net.js` | 156-159行目：3つの診断チャンネルの定義 |

**読解のコツ**: dc.channel()で通常チャンネル、dc.tracingChannel()でTracingChannelを作成している点を確認する。

#### Step 2: クライアント接続通知を理解する

Socket.connect()内での通知を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | net.js | `lib/net.js` | 1236-1240行目：net.client.socket通知 |

**主要処理フロー**:
1. **1231行目**: normalizeArgs()でオプション正規化
2. **1236-1240行目**: hasSubscribersチェックとpublish()

#### Step 3: サーバー接続受け入れ通知を理解する

onconnection()内での通知を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | net.js | `lib/net.js` | 2303-2307行目：net.server.socket通知 |

**主要処理フロー**:
- **2302行目**: connectionイベント発火
- **2303-2307行目**: hasSubscribersチェックとpublish()

#### Step 4: サーバーリッスン通知を理解する

Server.listen()とsetupListenHandle()での通知を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | net.js | `lib/net.js` | 2047-2049行目：asyncStart通知 |
| 4-2 | net.js | `lib/net.js` | 1920-1922行目、1944-1946行目：error通知 |
| 4-3 | net.js | `lib/net.js` | 1956-1958行目：asyncEnd通知 |

**主要処理フロー（Server.listen）**:
- **2047-2049行目**: asyncStart通知（リッスン開始時）

**主要処理フロー（setupListenHandle）**:
- **1920-1922行目**: error通知（ハンドル作成エラー時）
- **1944-1946行目**: error通知（listen()エラー時）
- **1956-1958行目**: asyncEnd通知（成功時）

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

```
net.connect() / socket.connect()
    │
    └─ Socket.prototype.connect() [1206行目]
           │
           └─ netClientSocketChannel.publish() [1236-1240行目]
                  └─ { socket: this }

Server.prototype.listen() [2015行目]
    │
    ├─ netServerListen.asyncStart.publish() [2048行目]
    │      └─ { server: this, options }
    │
    └─ listenInCluster() [1987行目]
           │
           └─ setupListenHandle() [1856行目]
                  │
                  ├─ [エラー時] netServerListen.error.publish() [1921行目, 1945行目]
                  │      └─ { server: this, error }
                  │
                  └─ [成功時] netServerListen.asyncEnd.publish() [1957行目]
                         └─ { server: this }

onconnection() [2244行目]
    │
    ├─ server.emit('connection', socket) [2302行目]
    │
    └─ netServerSocketChannel.publish() [2303-2307行目]
           └─ { socket }
```

### データフロー図

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

クライアント接続要求    Socket.connect              診断チャンネル購読者
    │                        │                            │
    ▼                        ▼                            ▼
options ──────────▶ connect() ───────────────▶ net.client.socket
    │                        │                            │
    │                        ▼                            ▼
    └─────────────▶ TCP/IPC接続処理


サーバーリッスン要求    Server.listen              診断チャンネル購読者
    │                        │                            │
    ▼                        ▼                            ▼
options ──────────▶ listen() ────────────────▶ net.server.listen:asyncStart
    │                        │                            │
    │                        ▼                            ▼
    │              setupListenHandle() ───────▶ asyncEnd または error


クライアント接続      onconnection              診断チャンネル購読者
    │                        │                            │
    ▼                        ▼                            ▼
TCP接続 ─────────▶ connectionイベント ─────▶ net.server.socket
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| net.js | `lib/net.js` | ソース | netモジュール実装、診断チャンネル通知 |
| diagnostics_channel.js | `lib/diagnostics_channel.js` | ソース | diagnostics_channelモジュール |
| tcp_wrap.cc | `src/tcp_wrap.cc` | ネイティブ | TCPバインディング |
| pipe_wrap.cc | `src/pipe_wrap.cc` | ネイティブ | Pipeバインディング |
