# 通知設計書 2-reconnecting

## 概要

本ドキュメントは、Etherpadにおける再接続中通知（reconnecting）の設計を記述する。

### 本通知の処理概要

この通知はサーバーへの再接続を試行中であることをユーザーに知らせるモーダルダイアログを表示する機能である。再接続中はツールバーにオーバーレイを表示し、ユーザーの編集操作を一時的にブロックする。ローディングアニメーション付きのモーダルでユーザーに待機を促す。

**業務上の目的・背景**：Etherpadはリアルタイム共同編集アプリケーションであり、ネットワーク障害や一時的な接続断が発生する可能性がある。再接続中であることを明示的に通知することで、ユーザーが編集内容の喪失を心配せずに済むようにし、システムが自動復旧を試みていることを伝える。また、ツールバーのオーバーレイにより再接続中の編集操作を防ぎ、データ整合性を保護する。

**通知の送信タイミング**：WebSocket接続が切断され、socket.ioが自動再接続を開始した時にトリガーされる。collabClientのチャンネル状態が「RECONNECTING」に変更されるとモーダルが表示される。

**通知の受信者**：再接続を試行しているユーザー本人のブラウザ上でのみ表示される。他のユーザーには通知されない。

**通知内容の概要**：「Reconnecting to your pad...」というメッセージとローディングアニメーション（スピナー）が表示される。ブランドロゴも表示され、処理中であることを視覚的に伝える。

**期待されるアクション**：ユーザーは再接続が完了するまで待機する。自動的に再接続されると「connected」通知に切り替わりモーダルが閉じる。

## 通知種別

アプリ内通知（モーダルダイアログ + オーバーレイ）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | 自動（socket.ioの再接続機能） |

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

接続が切断された現在のブラウザセッションのユーザーに対してのみ表示される。

## 通知テンプレート

### モーダル通知の場合

| 項目 | 内容 |
|-----|------|
| 表示要素 | `#connectivity .reconnecting` |
| タイトル | Reconnecting to your pad... |
| アニメーション | ローディングスピナー + ブランドロゴ |

### 本文テンプレート

```html
<div class="reconnecting">
  <h1 data-l10n-id="pad.modals.reconnecting"></h1>
  <i class='buttonicon buttonicon-spin5 icon-spin'>
    <img src='../static/img/brand.svg' class='etherpadBrand'><br/>
  </i>
</div>
```

### 添付ファイル

なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | この通知には変数がない | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| WebSocket切断 | disconnectイベント | socket.ioが再接続を試行 | 接続が切断され再接続処理が開始された時 |
| 再接続試行 | reconnect_attemptイベント | - | socket.ioの再接続試行イベント発火時 |
| RECONNECTING状態遷移 | channelState変更 | channelStateが'RECONNECTING'に変更 | collabClientの状態変更時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 既に切断済み | 完全に切断されconnected状態に遷移しない場合はDISCONNECTED通知に切り替わる |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[WebSocket切断検出] --> B[socket.on 'disconnect']
    B --> C[socketReconnecting関数呼び出し]
    C --> D[collabClient.setStateIdle]
    D --> E[collabClient.setIsPendingRevision true]
    E --> F[collabClient.setChannelState 'RECONNECTING']
    F --> G[handleChannelStateChange呼び出し]
    G --> H{newState === 'RECONNECTING'?}
    H -->|Yes| I[padeditor.disable]
    I --> J[padeditbar.disable]
    J --> K[padimpexp.disable]
    K --> L[padconnectionstatus.reconnecting]
    L --> M[padmodals.showModal 'reconnecting']
    M --> N[padmodals.showOverlay]
    N --> O[モーダル・オーバーレイ表示]
    H -->|No| P[他の状態処理]
```

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

### 参照テーブル一覧

| テーブル名 | 用途 | 備考 |
|-----------|------|------|
| なし | ローカルUI処理のみ | データベースアクセスなし |

### 更新テーブル一覧

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 再接続失敗 | 再接続試行が最大回数に達した場合 | DISCONNECTED状態に遷移 |
| 再接続タイムアウト | reconnect_failedイベント発火時 | エラーをスローまたはDISCONNECTED状態に遷移 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 5回（socket.io設定: reconnectionAttempts: 5） |
| リトライ間隔 | 1000〜5000ms（exponential backoff） |
| リトライ対象エラー | WebSocket接続エラー全般 |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（24時間対応）

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

- 通知はローカルブラウザ内でのみ処理される
- 再接続中はユーザー操作が制限されデータ整合性を保護
- XSS対策としてdata-l10n-id属性による国際化を使用

## 備考

- ローディングアニメーションはCSSクラス`buttonicon-spin5 icon-spin`で実装
- socket.ioの設定で再接続パラメータを調整可能（pad.ts 228-234行目）
- 国際化対応: pad.modals.reconnectingキーで翻訳される

---

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

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

### 推奨読解順序

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

再接続状態で使用されるデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pad_connectionstatus.ts | `src/static/js/pad_connectionstatus.ts` | status変数の構造（what: 'reconnecting'）を理解する |

**読解のコツ**: reconnecting関数はconnectedと同様の構造だが、showOverlayを呼び出す点が異なる。

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

再接続がトリガーされる起点を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pad.ts | `src/static/js/pad.ts` | socket.on('disconnect')ハンドラ（257-263行目） |
| 2-2 | pad.ts | `src/static/js/pad.ts` | socketReconnecting関数（248-255行目） |
| 2-3 | pad.ts | `src/static/js/pad.ts` | socket.io.on('reconnect_attempt')（280行目） |

**主要処理フロー**:
1. **257行目**: socket.on('disconnect')でdisconnectイベントを検出
2. **262行目**: socketReconnecting()を呼び出し
3. **253行目**: collabClient.setChannelState('RECONNECTING')を呼び出し

#### Step 3: 通知表示処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pad.ts | `src/static/js/pad.ts` | handleChannelStateChange関数のRECONNECTINGブランチ（659-663行目） |
| 3-2 | pad_connectionstatus.ts | `src/static/js/pad_connectionstatus.ts` | reconnecting関数（46-53行目） |
| 3-3 | pad_modals.ts | `src/static/js/pad_modals.ts` | showOverlay関数（45-48行目） |

**主要処理フロー**:
- **659-663行目（pad.ts）**: RECONNECTING時にeditor/editbar/impexpを無効化しreconnecting通知を表示
- **46-52行目（pad_connectionstatus.ts）**: status更新、モーダル表示、オーバーレイ表示

#### Step 4: HTMLテンプレートを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | pad.html | `src/templates/pad.html` | reconnecting divの構造（247-252行目） |

**主要処理フロー**:
- **247-252行目**: ローディングアニメーション付きのreconnecting表示

#### Step 5: socket.io設定を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | pad.ts | `src/static/js/pad.ts` | socketio.connect設定（228-234行目） |

**主要処理フロー**:
- **230行目**: reconnectionAttempts: 5（再接続試行回数）
- **232行目**: reconnectionDelay: 1000（初期待機時間）
- **233行目**: reconnectionDelayMax: 5000（最大待機時間）

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

```
socket.on('disconnect') (pad.ts:257)
    │
    └─ socketReconnecting (pad.ts:248)
           ├─ collabClient.setStateIdle (collab_client.ts:426)
           ├─ collabClient.setIsPendingRevision(true) (collab_client.ts:432)
           └─ collabClient.setChannelState('RECONNECTING') (collab_client.ts:355)
                  │
                  └─ callbacks.onChannelStateChange (collab_client.ts:358)
                         │
                         └─ pad.handleChannelStateChange (pad.ts:651)
                                ├─ padeditor.disable
                                ├─ padeditbar.disable
                                ├─ padimpexp.disable
                                └─ padconnectionstatus.reconnecting (pad_connectionstatus.ts:46)
                                       ├─ padmodals.showModal('reconnecting') (pad_modals.ts:35)
                                       └─ padmodals.showOverlay (pad_modals.ts:45)
```

### データフロー図

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

WebSocket                socket.io                     pad.ts
切断検出         ──▶     disconnectイベント発火         socketReconnecting
                              │                              │
                              ▼                              ▼
                         collabClient                   pad.handleChannelStateChange
                         setChannelState                     │
                         ('RECONNECTING')                    ▼
                                                        padconnectionstatus.reconnecting
                                                              │
                                                              ▼
                                                        padmodals.showModal + showOverlay
                                                              │
                                                              ▼
                                                        モーダル表示 + オーバーレイ表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pad.ts | `src/static/js/pad.ts` | ソース | socket.ioイベントハンドラ、状態管理 |
| pad_connectionstatus.ts | `src/static/js/pad_connectionstatus.ts` | ソース | 接続状態管理モジュール |
| pad_modals.ts | `src/static/js/pad_modals.ts` | ソース | モーダル・オーバーレイ表示制御 |
| collab_client.ts | `src/static/js/collab_client.ts` | ソース | WebSocket通信とリアルタイム同期 |
| pad.html | `src/templates/pad.html` | テンプレート | パッドのHTMLテンプレート |
| en.json | `src/locales/en.json` | 設定 | 国際化リソース（英語） |
| socketio.ts | `src/static/js/socketio.ts` | ソース | socket.ioクライアント設定 |
