# 通知設計書 13-ActionCable::Server::Broadcasting#broadcast

## 概要

本ドキュメントは、ActionCableのWebSocketブロードキャスト機能について、設計情報を記載するものである。

### 本通知の処理概要

ActionCable::Server::Broadcasting#broadcastは、ActionCableサーバーからWebSocket経由で接続中のクライアントに対してリアルタイムメッセージを配信する中核機能である。名前付きブロードキャストチャンネルに対してメッセージをパブリッシュし、そのチャンネルを購読しているすべてのクライアントに即座にメッセージを届ける。

**業務上の目的・背景**：従来のHTTPリクエスト・レスポンスモデルでは実現困難だったリアルタイム通知機能を提供する。チャットアプリケーション、ライブ通知、コラボレーションツール、ゲームなど、即座のデータ同期が必要なアプリケーションで使用される。サーバーサイドからクライアントへのプッシュ通知を可能にし、ポーリングの必要性を排除する。

**通知の送信タイミング**：アプリケーションコードから`ActionCable.server.broadcast(channel_name, message)`が呼び出された時点で、即座にメッセージが配信される。バックグラウンドジョブ、モデルコールバック、コントローラアクション等、任意の場所から呼び出し可能。

**通知の受信者**：指定したブロードキャストチャンネル名を`stream_from`で購読しているすべてのWebSocketクライアント。

**通知内容の概要**：JSON形式（デフォルト）またはカスタムエンコーディングされたメッセージ。通常はHashオブジェクトを渡し、クライアント側でJavaScriptオブジェクトとして受信される。

**期待されるアクション**：クライアント側のJavaScriptコードがメッセージを受信し、UIの更新、通知の表示、データの同期等のアクションを実行する。

## 通知種別

WebSocket通知（リアルタイムプッシュ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（即座にpubsubへパブリッシュ） |
| 優先度 | 高（リアルタイム配信） |
| リトライ | なし（pubsubアダプター依存） |

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

1. `ActionCable.server.broadcast(broadcasting, message)`でブロードキャスト名とメッセージを指定
2. ブロードキャスト名に対応するpubsubチャンネルにメッセージをパブリッシュ
3. 該当チャンネルを`stream_from`で購読しているすべての接続にメッセージが配信される

## 通知テンプレート

### WebSocket通知の場合

| 項目 | 内容 |
|-----|------|
| エンコーディング | JSON（ActiveSupport::JSON、デフォルト） |
| メッセージ形式 | カスタム（アプリケーション定義） |
| 圧縮 | pubsubアダプター設定に依存 |

### メッセージ形式例

```json
{
  "title": "New notification",
  "body": "You have a new message",
  "timestamp": "2026-03-01T12:00:00Z"
}
```

### 添付ファイル

| ファイル名 | 形式 | 条件 | 説明 |
|----------|------|------|------|
| N/A | - | - | WebSocket通知には添付ファイルの概念なし |

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| broadcasting | ブロードキャストチャンネル名 | 呼び出し元で指定 | Yes |
| message | 配信するメッセージ（Hash等） | 呼び出し元で指定 | Yes |
| coder | エンコーダー | デフォルトActiveSupport::JSON | No |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | ActionCable.server.broadcast | なし（即座に実行） | 直接呼び出し |
| モデルコールバック | after_create/after_update等 | モデル保存成功時 | データ変更時の自動通知 |
| バックグラウンドジョブ | ジョブ実行時 | ジョブ処理完了時 | 非同期処理結果の通知 |
| コントローラアクション | アクション実行時 | 任意の条件 | ユーザーアクションに応じた通知 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| pubsub未接続 | Redisなどのpubsubバックエンドに接続できない場合 |
| チャンネル名不正 | 空文字やnil指定の場合 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[ActionCable.server.broadcast呼び出し] --> B[broadcaster_for取得]
    B --> C[Broadcaster.broadcast実行]
    C --> D[ログ出力: Broadcasting to channel]
    D --> E[broadcast.action_cable計装イベント開始]
    E --> F[メッセージエンコード: coder.encode]
    F --> G[pubsub.broadcast呼び出し]
    G --> H{pubsubアダプター種別}
    H -->|Redis| I[Redis PUBLISH]
    H -->|PostgreSQL| J[PG NOTIFY]
    H -->|Inline| K[直接配信]
    I --> L[購読者へ配信]
    J --> L
    K --> L
    L --> M[broadcast.action_cable計装イベント終了]
    M --> N[クライアント受信]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | - | broadcastメソッド自体はDBを参照しない |

### 更新テーブル一覧

| テーブル名 | 操作 | 概要 |
|-----------|------|------|
| なし | - | broadcastメソッド自体はDBを更新しない |

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| pubsub接続エラー | Redis/PostgreSQL接続失敗 | pubsub設定を確認、接続をリトライ |
| エンコードエラー | messageがJSON化できない場合 | シリアライズ可能なオブジェクトを渡す |
| チャンネル名エラー | broadcastingがnilまたは不正 | 有効なチャンネル名を指定する |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし（pubsubアダプターに依存） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | 設定なし（pubsubの性能に依存） |
| 1日あたり上限 | 設定なし |

### 配信時間帯

制限なし（24時間365日配信可能）

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

- ブロードキャストチャンネル名は推測されにくい名前を使用する（例：ユーザーID入りのチャンネル名）
- 機密情報をブロードキャストに含める場合は、購読者の認証・認可を適切に行う
- クライアント側でのXSS対策（受信データのサニタイズ）を実施する
- WebSocket接続時のOrigin検証を有効にする

## 備考

- Redis pubsubアダプター使用時は、複数サーバー間でブロードキャストが共有される
- Inlineアダプターは開発・テスト用で、単一プロセスでのみ動作する
- `broadcaster_for`メソッドで再利用可能なBroadcasterオブジェクトを取得可能
- 計装イベント`broadcast.action_cable`でパフォーマンス監視が可能

---

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

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

### 推奨読解順序

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

ブロードキャストメッセージの構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | broadcasting.rb | `actioncable/lib/action_cable/server/broadcasting.rb` | Broadcastingモジュール全体、Broadcasterクラス |

**読解のコツ**: broadcastメソッドはシンプルで、メッセージをJSONエンコードしてpubsubに渡すだけ。複雑なロジックはpubsubアダプター側にある。

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

broadcastメソッドの実装を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | broadcasting.rb | `actioncable/lib/action_cable/server/broadcasting.rb` | broadcastメソッド、broadcaster_forメソッド |

**主要処理フロー**:
1. **行33-35**: `broadcast(broadcasting, message, coder:)`メソッドがbroadcaster_for経由でBroadcaster.broadcastを呼び出す
2. **行40-42**: `broadcaster_for(broadcasting, coder:)`でBroadcasterインスタンスを生成
3. **行45-50**: Broadcasterクラスのコンストラクタでserver、broadcasting、coderを保持

#### Step 3: Broadcasterクラスの動作を理解する

実際のブロードキャスト処理を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | broadcasting.rb | `actioncable/lib/action_cable/server/broadcasting.rb` | Broadcaster#broadcastメソッド |

**主要処理フロー**:
- **行52-53**: ログ出力「Broadcasting to {broadcasting}: {message}」
- **行55-56**: 計装ペイロード作成（broadcasting、message、coder）
- **行56-59**: `ActiveSupport::Notifications.instrument("broadcast.action_cable", payload)`で計装
- **行57**: `coder.encode(message)`でメッセージをエンコード（JSONなど）
- **行58**: `server.pubsub.broadcast(broadcasting, encoded)`でpubsubに配信

#### Step 4: pubsubアダプターを理解する

Redisなどのpubsubアダプターの動作を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | redis.rb | `actioncable/lib/action_cable/subscription_adapter/redis.rb` | Redis pubsubアダプター |
| 4-2 | postgresql.rb | `actioncable/lib/action_cable/subscription_adapter/postgresql.rb` | PostgreSQL NOTIFYアダプター |
| 4-3 | inline.rb | `actioncable/lib/action_cable/subscription_adapter/inline.rb` | 開発用インラインアダプター |

**主要処理フロー**:
- 各アダプターの`broadcast(channel, message)`メソッドが実際の配信を担当

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

```
ActionCable.server.broadcast(broadcasting, message)
    │
    ├─ ActionCable::Server::Broadcasting#broadcast (行33-35)
    │      └─ broadcaster_for(broadcasting, coder: coder) (行40-42)
    │             └─ Broadcaster.new(self, String(broadcasting), coder: coder)
    │
    └─ Broadcaster#broadcast(message) (行52-60)
           │
           ├─ server.logger.debug (行53)
           │
           ├─ ActiveSupport::Notifications.instrument("broadcast.action_cable") (行56-59)
           │      │
           │      ├─ coder.encode(message) (行57)
           │      │      └─ ActiveSupport::JSON.encode (デフォルト)
           │      │
           │      └─ server.pubsub.broadcast(broadcasting, encoded) (行58)
           │             │
           │             ├─ Redis::PUBLISH (Redisアダプター)
           │             ├─ PG::NOTIFY (PostgreSQLアダプター)
           │             └─ 直接配信 (Inlineアダプター)
           │
           └─ 各購読者のstream_handlerが呼び出される
                  └─ クライアントへWebSocket送信
```

### データフロー図

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

broadcasting ─────────────┬───▶ Broadcaster.new ───▶ @broadcasting
                          │
message (Hash) ───────────┼───▶ coder.encode ───▶ JSON文字列
                          │
coder (default: JSON) ────┘

                          │
                          ▼
                   pubsub.broadcast
                          │
                          ▼
               ┌─────────────────────┐
               │   pubsub backend    │
               │ (Redis/PG/Inline)   │
               └─────────────────────┘
                          │
                          ▼
               ┌─────────────────────┐
               │  Subscribers        │
               │  (stream_from)      │
               └─────────────────────┘
                          │
                          ▼
               ┌─────────────────────┐
               │  WebSocket Clients  │
               └─────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| broadcasting.rb | `actioncable/lib/action_cable/server/broadcasting.rb` | ソース | Broadcastingモジュール、Broadcasterクラス |
| base.rb | `actioncable/lib/action_cable/subscription_adapter/base.rb` | ソース | pubsubアダプター基底クラス |
| redis.rb | `actioncable/lib/action_cable/subscription_adapter/redis.rb` | ソース | Redis pubsubアダプター |
| postgresql.rb | `actioncable/lib/action_cable/subscription_adapter/postgresql.rb` | ソース | PostgreSQL NOTIFYアダプター |
| inline.rb | `actioncable/lib/action_cable/subscription_adapter/inline.rb` | ソース | 開発用インラインアダプター |
| streams.rb | `actioncable/lib/action_cable/channel/streams.rb` | ソース | stream_from購読処理 |
| notifications.rb | `activesupport/lib/active_support/notifications.rb` | ソース | 計装イベント基盤 |
