# 通知設計書 22-served/updateDCD

## 概要

本ドキュメントは、serve-d LSPサーバーにおけるカスタム通知「served/updateDCD」の設計仕様を定義する。本通知はクライアント(エディタ)からサーバーに送信され、DCDの更新・インストールプロセスを開始する。

### 本通知の処理概要

本通知は、DCD（D Completion Daemon）のバイナリをダウンロードまたはソースからビルドしてインストールする処理を起動する。

**業務上の目的・背景**：DCDはD言語の自動補完エンジンであり、serve-dが提供するコード補完機能の中核を担う。DCDが未インストール、またはバージョンが古い場合に、クライアントからの明示的な要求またはサーバーの自動判定によりDCDの更新が行われる。これにより、常に最新のDCDを利用した高品質な自動補完機能を提供できる。

**通知の送信タイミング**：以下のいずれかの条件で送信される。(1) ユーザーがエディタのコマンドパレットから「Update DCD」を実行した場合。(2) サーバー起動時にDCDが古いと判定され、d.aggressiveUpdateがtrueの場合に自動的にspawnFiberで起動される。(3) DCD更新確認ダイアログでユーザーが更新を選択した場合。

**通知の受信者**：serve-d LSPサーバープロセスが受信者である。

**通知内容の概要**：パラメータなし。通知受信後、サーバーはプラットフォームに応じてDCDバイナリをダウンロードするか、ソースからビルドする。

**期待されるアクション**：サーバーはDCDのインストール/更新を実行し、完了後にcoded/logInstallで進捗を通知し、coded/updateSettingでクライアント設定を更新し、各ワークスペースでDCDサーバーを起動する。

## 通知種別

LSPカスタム通知（JSON-RPC Notification）。クライアントからサーバーへの方向（C->S）。

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 非同期（JSON-RPC notification） |
| 優先度 | 高 |
| リトライ | なし（通知のため応答なし） |

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

クライアントがserve-d LSPサーバーに直接送信する。サーバー内部ではdcd_update.dモジュールのupdateDCD()関数がファイバーとして実行される。

## 通知テンプレート

### メール通知の場合

該当なし。本通知はLSPプロトコル上のJSON-RPCメッセージである。

### 本文テンプレート

```json
{
  "jsonrpc": "2.0",
  "method": "served/updateDCD"
}
```

### 添付ファイル

該当なし。

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| （なし） | 本通知にパラメータは存在しない | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| 画面操作 | ユーザーがコマンドパレットから「Update DCD」を選択 | なし | DCD手動更新 |
| 自動 | サーバー起動時にDCDが古い場合 | d.aggressiveUpdate == true | 自動更新 |
| 画面操作 | DCD更新確認ダイアログで更新ボタンを選択 | ユーザーが更新を選択 | ダイアログ経由の更新 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| dcdUpdating == true | 既にDCD更新中の場合、二重実行を防止（dcdUpdatingフラグで管理） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[served/updateDCD通知受信] --> B[dcdUpdateReason確認]
    B --> C[coded/logInstall: インストール開始ログ]
    C --> D[出力フォルダ決定・既存ファイル削除]
    D --> E{ソースビルド or バイナリダウンロード?}
    E -->|ソースビルド| F[compileDependency実行]
    E -->|バイナリダウンロード| G[downloadFile実行]
    F --> H[実行ファイル存在確認]
    G --> H
    H --> I{成功?}
    I -->|Yes| J[coded/updateSetting: パス設定更新]
    I -->|No| K[coded/logInstall: 失敗ログ]
    J --> L[全ワークスペースでDCDサーバー起動]
    L --> M[coded/logInstall: 成功ログ]
    K --> N[終了]
    M --> N
```

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

### 参照テーブル一覧

該当なし。本通知はデータベースを使用しない。ファイルシステム上のバイナリファイルを操作する。

### 更新テーブル一覧

該当なし。

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| ダウンロード失敗 | ネットワークエラー等 | coded/logInstallでエラーメッセージを送信。手動ダウンロードの案内を表示 |
| ビルド失敗 | ソースビルド時のコンパイルエラー | coded/logInstallでエラーメッセージを送信 |
| 実行ファイル未発見 | ダウンロード・ビルド後に実行ファイルが見つからない | coded/logInstallで失敗通知。手動パス設定を案内 |
| バージョン確認失敗 | dcd-server --versionが失敗 | coded/logInstallでエラー出力を送信 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 1分あたり上限 | dcdUpdatingフラグにより同時実行は1つに制限 |
| 1日あたり上限 | 制限なし |

### 配信時間帯

制限なし。

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

- DCDバイナリはGitHub Releases（https://github.com/dlang-community/DCD）からHTTPSでダウンロードされる
- ソースビルドの場合はGitリポジトリからクローンされる
- ダウンロードされたバイナリの署名検証は実装されていない
- 出力先はプラットフォーム固有のユーザーローカルディレクトリ（~/.local/share/code-d/bin等）

## 備考

- バンドルDCDバージョンはv0.15.2（dcd_update.d L124で定義）
- プラットフォームに応じてバイナリダウンロードかソースビルドかが自動判定される
- 更新完了後、coded/updateSettingでdcdClientPathとdcdServerPathがクライアントに通知される
- 更新完了後、全ワークスペースでDCDサーバーが再起動される

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | types.d | `source/served/types.d` | UpdateSettingParamsの定義（coded/updateSettingのパラメータ） |

**読解のコツ**: UpdateSettingParamsはsection, value, globalの3フィールドを持つ構造体。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | dcd_update.d | `source/served/commands/dcd_update.d` | updateDCD関数（L82-307）が通知ハンドラ |

**主要処理フロー**:
1. **L82**: `@protocolNotification("served/updateDCD")` アノテーション
2. **L83-88**: scope(exit)でdcdUpdatingとdcdUpdateReasonをリセット
3. **L91-94**: coded/logInstallでインストール開始を通知
4. **L96-112**: 出力フォルダの決定と既存ファイルの削除
5. **L126-129**: ソースビルドかバイナリダウンロードかの判定
6. **L133-153**: ソースからのビルド処理
7. **L155-237**: バイナリダウンロード処理
8. **L239-268**: 実行ファイル存在確認とバージョンチェック
9. **L270-273**: coded/updateSettingでクライアント設定更新
10. **L275-306**: 成功時のDCDサーバー起動処理

#### Step 3: 自動更新トリガーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | extension.d | `source/served/extension.d` | doGlobalStartup関数（L363-484）でDCDバージョンチェックと更新起動 |

**主要処理フロー**:
- **L426-473**: DCDが古い場合の処理分岐。aggressiveUpdateがtrueならspawnFiber("updateDCD")で自動更新
- **L438-439**: 自動更新の場合
- **L442-471**: ユーザー確認ダイアログ経由の場合

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

```
[クライアント] served/updateDCD通知
    |
    +-- RPCProcessor
          |
          +-- updateDCD() [dcd_update.d L83]
                |
                +-- rpc.notifyMethod("coded/logInstall", ...) [進捗通知]
                |
                +-- determineOutputFolder() [L96]
                |
                +-- compileDependency() または downloadFile() [ビルド/ダウンロード]
                |
                +-- rpc.notifyMethod("coded/updateSetting", ...) [設定更新]
                |
                +-- lazyStartDCDServer() [DCDサーバー起動]
```

### データフロー図

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

JSON-RPC通知       updateDCD()                         coded/logInstall通知
(パラメータなし) --> [dcd_update.d]                  --> coded/updateSetting通知
                   GitHub/ソースからDCDを取得         --> DCDバイナリ（ファイルシステム）
                   設定更新・DCDサーバー起動
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| dcd_update.d | `source/served/commands/dcd_update.d` | ソース | updateDCD通知ハンドラ（メイン処理） |
| extension.d | `source/served/extension.d` | ソース | doGlobalStartup内での自動更新トリガー |
| git_build.d | `source/served/io/git_build.d` | ソース | Gitリポジトリからのビルド処理 |
| http_wrap.d | `source/served/io/http_wrap.d` | ソース | HTTPダウンロード処理 |
| types.d | `source/served/types.d` | ソース | UpdateSettingParamsの定義 |
| jsonrpc.d | `lsp/source/served/lsp/jsonrpc.d` | ソース | JSON-RPC通信基盤 |
