# 通知設計書 3-disconnected

## 概要

本ドキュメントは、Etherpadにおける汎用切断通知（disconnected）の設計を記述する。

### 本通知の処理概要

この通知はサーバーとの接続が切断されたことをユーザーに知らせるモーダルダイアログを表示する機能である。切断理由が特定のカテゴリ（userdup, unauth, loopingなど）に該当しない場合のフォールバック通知として機能し、自動再接続タイマーと手動再接続ボタンを提供する。

**業務上の目的・背景**：Etherpadはリアルタイム共同編集アプリケーションであり、サーバーとの接続が切れると編集内容の同期ができなくなる。ユーザーに切断状態を明確に通知し、再接続の方法を提示することで、作業の中断を最小限に抑え、データ損失のリスクを軽減する。自動再接続機能により、ユーザーの手動操作なしで復旧を試みる。

**通知の送信タイミング**：WebSocket接続が切断され、特定の切断理由（badChangeset、corruptPad、deleted、initsocketfail、looping、rateLimited、rejected、slowcommit、unauth、userdup）に該当しない場合にトリガーされる。汎用的な切断通知として機能する。

**通知の受信者**：接続が切断されたユーザー本人のブラウザ上でのみ表示される。

**通知内容の概要**：「You have been disconnected.」というタイトルと、「The connection to the server was lost」という説明、「The server may be unavailable. Please notify the service administrator if this continues to happen.」という原因説明が表示される。「Force reconnect」ボタンと自動再接続カウントダウンタイマーも表示される。

**期待されるアクション**：ユーザーは自動再接続を待つか、「Force reconnect」ボタンをクリックして手動で再接続を試みる。

## 通知種別

アプリ内通知（モーダルダイアログ + オーバーレイ + 自動再接続タイマー）

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期 |
| 優先度 | 高 |
| リトライ | 自動（自動再接続タイマー） |

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

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

## 通知テンプレート

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

| 項目 | 内容 |
|-----|------|
| 表示要素 | `#connectivity .disconnected` |
| タイトル | You have been disconnected. |
| 説明 | The connection to the server was lost |
| 原因 | The server may be unavailable. Please notify the service administrator if this continues to happen. |

### 本文テンプレート

```html
<div class="disconnected with_reconnect_timer">
  <h1 data-l10n-id="pad.modals.disconnected"></h1>
  <h2 data-l10n-id="pad.modals.disconnected.explanation"></h2>
  <p id="defaulttext" data-l10n-id="pad.modals.disconnected.cause"></p>
  <button id="forcereconnect" class="btn btn-primary" data-l10n-id="pad.modals.forcereconnect"></button>
</div>
```

### 添付ファイル

なし

## テンプレート変数

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

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| WebSocket切断 | DISCONNECTED状態遷移 | 特定理由に該当しない場合 | collabClientのchannelStateがDISCONNECTEDに変更時 |
| 再接続失敗 | reconnect_failedイベント | 全再接続試行が失敗 | socket.ioの再接続がタイムアウトした時 |
| サーバーからの切断指示 | message.disconnect | 汎用切断理由 | サーバーが切断を指示した時 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 特定切断理由 | knownReasons配列に含まれる理由の場合は専用モーダルを表示 |
| 既に切断状態 | status.whatが既に'disconnected'の場合は重複処理しない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[WebSocket切断検出] --> B[padconnectionstatus.disconnected msg呼び出し]
    B --> C{status.what === 'disconnected'?}
    C -->|Yes| D[処理終了/重複防止]
    C -->|No| E[statusを'disconnected'に更新]
    E --> F{msgがknownReasonsに含まれる?}
    F -->|Yes| G[特定のモーダルIDを使用]
    F -->|No| H[フォールバックで'disconnected'を使用]
    G --> I[padmodals.showModal messageId]
    H --> I
    I --> J[padmodals.showOverlay]
    J --> K[with_reconnect_timerの場合]
    K --> L[自動再接続タイマー表示]
    L --> M[カウントダウン開始]
    M --> N{タイマー期限切れ?}
    N -->|Yes| O[自動再接続実行]
    N -->|No| P[ユーザーがキャンセル/再接続ボタン押下]
```

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

### 参照テーブル一覧

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

### 更新テーブル一覧

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

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 再接続失敗 | Force reconnectがタイムアウト | ページリロードを促す |
| ネットワーク不通 | サーバーに到達できない | カウントダウン後に再試行 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 無制限（ユーザーがキャンセルするまで） |
| リトライ間隔 | clientVars.automaticReconnectionTimeout × 2^n 秒 |
| リトライ対象エラー | ネットワーク切断エラー |

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（24時間対応）

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

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

## 備考

- with_reconnect_timerクラスにより自動再接続機能が有効化される
- 自動再接続タイマーはpad_automatic_reconnect.tsで実装
- 再接続間隔は指数バックオフで増加（2^n倍）
- 国際化対応: pad.modals.disconnected, pad.modals.disconnected.explanation, pad.modals.disconnected.causeキーで翻訳

---

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

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

### 推奨読解順序

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

切断状態で使用されるデータ構造を把握する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pad_connectionstatus.ts | `src/static/js/pad_connectionstatus.ts` | status変数の構造（what, why）とknownReasons配列（65-77行目） |

**読解のコツ**: knownReasons配列には特定の切断理由が列挙されており、これに該当しない場合はフォールバックでdisconnectedが使用される。

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

切断通知がトリガーされる起点を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | pad.ts | `src/static/js/pad.ts` | handleChannelStateChange関数のDISCONNECTEDブランチ（664-688行目） |
| 2-2 | pad.ts | `src/static/js/pad.ts` | socket.on('message')でのdisconnect処理（333-342行目） |

**主要処理フロー**:
1. **333行目**: obj.disconnectがある場合
2. **334行目**: padconnectionstatus.disconnected(obj.disconnect)を呼び出し
3. **664行目**: handleChannelStateChangeでDISCONNECTED状態処理

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | pad_connectionstatus.ts | `src/static/js/pad_connectionstatus.ts` | disconnected関数（54-86行目）の実装 |
| 3-2 | pad_modals.ts | `src/static/js/pad_modals.ts` | showModal関数での自動再接続タイマー連携（41行目） |
| 3-3 | pad_automatic_reconnect.ts | `src/static/js/pad_automatic_reconnect.ts` | 自動再接続タイマーの実装（5-18行目） |

**主要処理フロー**:
- **54-55行目（pad_connectionstatus.ts）**: 既にdisconnectedの場合は早期リターン
- **57-60行目**: statusをdisconnectedに更新、理由を保存
- **78-82行目**: knownReasonsにない場合は'disconnected'にフォールバック
- **84-85行目**: モーダル表示とオーバーレイ表示

#### Step 4: 自動再接続タイマーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | pad_automatic_reconnect.ts | `src/static/js/pad_automatic_reconnect.ts` | showCountDownTimerToReconnectOnModal（5-18行目） |
| 4-2 | pad_automatic_reconnect.ts | `src/static/js/pad_automatic_reconnect.ts` | CountDownTimerクラス（129-196行目） |
| 4-3 | pad_automatic_reconnect.ts | `src/static/js/pad_automatic_reconnect.ts` | reconnectionTries（113-123行目） |

**主要処理フロー**:
- **6行目**: with_reconnect_timerクラスを持つモーダルのみ対象
- **56-74行目**: タイマー作成と期限切れ時の処理
- **117-121行目**: 再接続試行回数による待機時間の指数増加

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 5-1 | pad.html | `src/templates/pad.html` | disconnected divの構造（304-311行目） |

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

```
socket.on('message') (pad.ts:303)
    │ or
handleChannelStateChange (pad.ts:651)
    │
    └─ padconnectionstatus.disconnected(msg) (pad_connectionstatus.ts:54)
           ├─ status更新 (what: 'disconnected', why: msg)
           ├─ knownReasons判定
           ├─ padmodals.showModal(k) (pad_modals.ts:35)
           │      ├─ padeditbar.toggleDropDown('none')
           │      ├─ CSS class切り替え
           │      ├─ automaticReconnect.showCountDownTimerToReconnectOnModal
           │      │      ├─ createCountDownElementsIfNecessary
           │      │      ├─ createTimerForModal
           │      │      │      └─ new CountDownTimer
           │      │      └─ enableAutomaticReconnection
           │      └─ padeditbar.toggleDropDown('connectivity')
           │
           └─ padmodals.showOverlay (pad_modals.ts:45)
```

### データフロー図

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

サーバーからの            pad.ts                        pad_connectionstatus.ts
disconnect指示    ──▶     socket.on('message')          disconnected(msg)
     or                        │                              │
WebSocket切断                  ▼                              ▼
                         handleChannelStateChange       knownReasons判定
                              │                              │
                              ▼                              ▼
                         padconnectionstatus            padmodals.showModal
                         .disconnected                       │
                                                              ▼
                                                        pad_automatic_reconnect
                                                        .showCountDownTimer
                                                              │
                                                              ▼
                                                        モーダル + タイマー表示
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| pad.ts | `src/static/js/pad.ts` | ソース | メインモジュール、イベントハンドラ |
| pad_connectionstatus.ts | `src/static/js/pad_connectionstatus.ts` | ソース | 接続状態管理、切断理由判定 |
| pad_modals.ts | `src/static/js/pad_modals.ts` | ソース | モーダル表示制御 |
| pad_automatic_reconnect.ts | `src/static/js/pad_automatic_reconnect.ts` | ソース | 自動再接続タイマー実装 |
| collab_client.ts | `src/static/js/collab_client.ts` | ソース | WebSocket通信 |
| pad.html | `src/templates/pad.html` | テンプレート | HTMLテンプレート |
| en.json | `src/locales/en.json` | 設定 | 国際化リソース |
