# 非機能要件定義書

## 概要

本ドキュメントは、serve-d（D言語向けLanguage Server Protocol実装）プロジェクトのソースコードから抽出・推定された非機能要件を定義する。serve-dは、エディタとの間でJSON-RPCベースのLSP通信を行い、D言語のコード補完、静的解析、フォーマット、リファクタリング等のIDE機能を提供するサーバープロセスである。

## 性能要件

### レスポンスタイム

| 処理種別 | 目標値 | 備考 |
| --- | --- | --- |
| LSPリクエスト応答（一般） | 数百ms以内 | Fiber（コルーチン）ベースの並行処理により、RPCメインループは10msインターバルで処理を回す（`serverbase.d` `runImpl` メソッド `loopIterationDelay = 10.msecs`）。個々のリクエストはFiberとして非同期にディスパッチされる |
| テキスト変更時のリンティング（小ファイル） | 50ms遅延後に実行 | ファイルサイズが50KiB以下の場合、`onDidChangeDocument` で50ms後にdfmtリンティングを実行（`source/served/extension.d` L1157） |
| テキスト変更時のリンティング（大ファイル） | 500ms遅延後に実行 | ファイルサイズが50KiBを超える場合、dfmtリンティングの遅延を500msに拡大（`source/served/extension.d` L1157） |
| テキスト変更時のDScannerリンティング（小ファイル） | 200ms遅延後に実行 | ファイルサイズが50KiB以下の場合（`source/served/extension.d` L1179） |
| テキスト変更時のDScannerリンティング（大ファイル） | 1000ms遅延後に実行 | ファイルサイズが50KiBを超える場合（`source/served/extension.d` L1179） |
| HTTPダウンロード進捗通知 | 1秒間隔 | DCD等の依存バイナリダウンロード中、1秒ごとにFiber.yieldして進捗をクライアントに通知（`http/source/served/http.d` L78, L101） |

### スループット

| 項目 | 目標値 | 備考 |
| --- | --- | --- |
| 同時リクエスト処理 | Fiber数に依存（制限なし） | リクエストごとにFiberが生成され、FiberManagerにより協調スケジューリングされる。同時接続数の明示的な上限はコード上に設定されていない |
| RPCメインループ周期 | 10ms | メインループはRPC処理とFiber呼び出しを10ms間隔で行う（`serverbase.d` L460, L566） |
| Fiber呼び出し頻度 | 毎ループ100回/秒（parallelMain） | `parallelMain` のコメントに「Called at most 100x per second」と記載（`serverbase/source/served/utils/async.d` L30） |
| ファイル読み込みバッファ | 4096バイト | stdin/ファイルからの読み込みバッファサイズ（`lsp/source/served/lsp/filereader.d` 各Reader実装） |

### メモリ管理

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| Fiberスタックサイズ（デフォルト） | 4096 * ページ数 バイト | `fiberPageSize = 4096`（`serverbase.d` L28）。デフォルトページ数はデバッグビルドで128ページ（1MiB）、リリースビルドで32ページ（256KiB）（`source/served/types.d` L16-18） |
| RPCプロセッサFiberサイズ | 4096 * 32 = 128KiB | `RPCProcessor` のFiber生成時（`lsp/source/served/lsp/jsonrpc.d` L25） |
| joinAll用Fiberサイズ | 4096 * 48 = 192KiB | 大きいファイルパース時のlibdparseセグフォルト防止のため（`serverbase/source/served/utils/fibermanager.d` L122のコメント） |
| GC定期収集間隔 | 30秒 | `gcCollectSeconds = 30`（`serverbase.d` L38） |
| GC最小化頻度 | 5回に1回 | `gcMinimizeTimes = 5`：GC.collectの5回に1回GC.minimizeを実行（`serverbase.d` L40） |
| コード読み込み最大サイズ | 50KiB（デフォルト） | `readCodeWithBuffer` の `maxLen = 1024 * 50`（`lsp/source/served/lsp/filereader.d` L376） |

## 可用性要件

| 項目 | 目標値 | 備考 |
| --- | --- | --- |
| 稼働率 | エディタプロセスに依存 | serve-dはエディタから起動されるサブプロセスであり、独立した稼働率目標は定義されていない。エディタのライフサイクルに連動する |
| 計画停止時間 | 該当なし | エディタ終了時にLSP shutdown/exit で正常終了する設計 |
| 障害復旧時間（RTO） | 即時（プロセス再起動） | エディタが再起動すればserve-dも再起動される。DCD等のサブコンポーネントはクラッシュ時にFiberベースで自動再起動される（`source/served/extension.d` L960-968 `handleCrash`） |
| 目標復旧時点（RPO） | 該当なし | serve-dは永続データを持たない。全ての状態はメモリ上にのみ存在し、再起動時にワークスペースから再構築される |

### 障害対策

- **クラッシュハンドラ**: Linux/macOSでは `SIGABRT`, `SIGALRM`, `SIGILL`, `SIGINT`, `SIGKILL`, `SIGPIPE`, `SIGSEGV`, `SIGTRAP` のシグナルハンドラを登録し、バックトレースを出力して終了する（`source/crash_handler.d`）
- **DCDサーバー自動再起動**: DCDコンポーネントがクラッシュした場合、`handleCrash` メソッドが自動的にFiberを生成してDCDサーバーを再起動する（`source/served/extension.d` L960-968）
- **致命的エラーからの回復**: リクエスト処理中の `Throwable`（致命的エラー）をキャッチし、エラーメッセージをクライアントに表示しつつサーバーの実行を継続する設計（`serverbase.d` L405-417, L429-443）
- **ファイルシステムアクセスのnothrow化**: ディレクトリ走査を `NothrowDirIterator` でラップし、`FileException` や `UTFException` が発生してもクラッシュしない設計（`source/served/io/nothrow_fs.d`）
- **遅延読み込み（Lazy Loading）**: `LazyWorkspaceD` によるコンポーネントの遅延初期化を実装し、大規模プロジェクトでの起動時の負荷を分散（`source/served/backend/lazy_workspaced.d`）
- **多プロジェクト制御**: `manyProjectsThreshold`（デフォルト6）を超えるサブプロジェクトがある場合、ユーザーに読み込み可否を問い合わせるか、スキップする制御機構を持つ（`source/served/types.d` L114, `source/served/extension.d` L741-773）

## セキュリティ要件

### 通信経路

- **stdin/stdout経由のJSON-RPC通信**: serve-dはstdin/stdoutを使用してLSPクライアントと通信する。ネットワークを経由しないプロセス間通信のため、通信路の暗号化は不要である
- **stdoutの保護**: 起動時にstdoutをstderrにリダイレクトし、通常のwriteln呼び出しがRPC出力に混入することを防止（`serverbase/source/served/serverbase.d` L12-23）
- **DCD通信ポート**: DCDサーバーとの通信にはポート9166がデフォルトで使用される（`source/served/extension.d` L380）。DCDとの通信はローカルホスト内に限定される

### ファイルシステムアクセス

- **ワークスペース境界**: serve-dはクライアントから指定されたワークスペースフォルダ配下のファイルのみを操作対象とする
- **ダウンロードファイルの配置先**: DCD等の依存バイナリは、プラットフォーム固有のユーザーデータディレクトリに配置される（Linux: `~/.local/share/code-d/bin` または `~/.code-d/bin`、Windows: `%APPDATA%/code-d/bin`、macOS: `~/.code-d/bin`）（`source/served/extension.d` L1057-1076）
- **Windows SSL処理**: Windows環境ではHTTPダウンロード時にSSL検証をスキップする設定がある（`dub.json` の `"versions-windows": ["RequestsSkipSSL"]`）

### 入力検証

- **JSON-RPCプロトコル準拠検証**: 受信したJSON-RPCメッセージについて、`Content-Length` ヘッダの存在確認、JSONフォーマットの検証、必須フィールドの存在確認、paramsの型チェック（object/array以外を拒否）を実施（`lsp/source/served/lsp/jsonrpc.d` L479-676）
- **コマンドライン引数の検証**: `--require` フラグで指定された機能セットがサポートされていない場合、意図的にクラッシュ（エラー終了）する設計（`source/app.d` L152-163）

## 拡張性要件

### モジュール構成

serve-dは以下のサブパッケージに分割されたモジュラー設計を採用している。

| サブパッケージ | 責務 |
| --- | --- |
| `serve-d:http` | HTTPファイルダウンロード（プラットフォーム別実装） |
| `serve-d:protocol` | LSPプロトコル型定義 |
| `serve-d:lsp` | LSP JSON-RPCプリミティブ |
| `serve-d:serverbase` | LSPサーバー基盤（任意言語向け汎用フレームワーク） |
| `serve-d:dcd` | DCD（D Completion Daemon）クライアント |
| `serve-d:workspace-d` | D言語コア機能（libdparse, dfmt, D-Scanner, DCD連携） |
| `source/` | LSPコマンドとワークスペースの橋渡し |

### プラグインアーキテクチャ

- **コンポーネントベース設計**: `WorkspaceD` のコンポーネントシステムにより、DubComponent, DCDComponent, DscannerComponent, DfmtComponent等の機能モジュールを動的に登録・解除可能（`source/served/extension.d` L392-414）
- **遅延コンポーネント読み込み**: `LazyWorkspaceD` による遅延コンポーネント初期化で、実際にアクセスされるまで初期化コストを回避（`source/served/backend/lazy_workspaced.d`）
- **UDAベースのイベントディスパッチ**: `@protocolMethod`, `@protocolNotification`, `@onConfigChanged` 等のUDA（User-Defined Attributes）によりイベントハンドラを宣言的に定義し、コンパイル時にディスパッチテーブルを構築
- **`--provide` フラグ**: エディタの機能レベルに応じて振る舞いを切り替えるプロバイダ機構（`http`, `implement-snippets`, `context-snippets`, `default-snippets`, `test-runner`, `tasks-current`, `async-ask-load`）

### マルチワークスペース対応

- **複数ワークスペースフォルダ**: LSP仕様のワークスペースフォルダ機能を完全サポートし、動的なワークスペースの追加・削除が可能（`source/served/extension.d` L1101-1112）
- **ワークスペース別設定**: `perWorkspaceConfigurationStore` による個別設定管理（`serverbase/source/served/utils/serverconfig.d`）

### マルチプラットフォーム対応

- **対応プラットフォーム**: Linux（x86_64）、Windows（x86/x86_64）、macOS（x86_64/AArch64）
- **プラットフォーム固有実装**: stdin読み込み（`PosixStdinReader` / `WindowsStdinReader`）、HTTPダウンロード（WinHTTP / requests library）で分岐
- **多言語UI**: `--lang` オプションによるGUIメッセージの言語切り替え対応（`source/served/utils/translate.d`）

## 保守性要件

### テスト

- **ユニットテスト**: dub標準のユニットテスト機構を使用し、各サブパッケージに対して個別テストを実施。CIではdmd-latest及びldc-latestの2コンパイラで検証
- **テストマトリクス**: ubuntu-22.04, windows-latest, macos-latestの3 OS環境で自動テスト実行（`.github/workflows/unittest.yml`）
- **テストタイムアウト**: CI上で各テストステップに5分～30分のタイムアウトが設定されている
- **モックRPC**: テスト用の `MockRPC` ユーティリティにより、RPCプロセッサの通信を模擬可能（`lsp/source/served/lsp/jsonrpc.d` L681-747）

### ビルド・デプロイ

- **ビルドシステム**: DUB（D言語パッケージマネージャ）を使用
- **ビルド最適化**: `-lowmem` フラグによるメモリ使用量の抑制（`dub.json` L6）
- **ナイトリービルド**: 毎日UTC 2:00にGitHub Actionsで自動ビルド・デプロイ（`.github/workflows/nightly.yml`）
- **リリースバイナリ**: Linux/Windows/macOSのマルチプラットフォーム向けに事前ビルドバイナリを提供

### コード品質

- **構造化ログ**: `std.experimental.logger` による構造化ログ出力。ログレベルはコマンドライン `--loglevel` で切り替え可能（trace, info, warning, error等）
- **パフォーマンストレースログ**: `debug = PerfTraceLog` によるパフォーマンス計測ログの出力機能。GC統計情報、関数ごとの実行時間・GCアロケーション量を `served_trace.log` に出力（`source/served/utils/trace.d`）
- **ライセンス**: MITライセンス

## 運用・監視要件

### ログ出力

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| デフォルトログ出力先 | stderr | stdoutはRPC通信に使用されるため、ログはstderrに出力される |
| ログファイル出力 | `--logfile` オプション | 任意のファイルにログ出力可能 |
| デフォルトログレベル | debug/nightlyビルド: `verbose`、リリースビルド: `info` | `source/app.d` L79-80 |
| 進捗ログ | `window/logMessage` 通知 | 各種進捗情報を `[progress]` プレフィックス付きでクライアントに送信（`source/served/utils/progress.d`） |
| インストールログ | `coded/logInstall` 通知 | DCD等の依存コンポーネントインストール時のログをクライアントに送信 |

### 監視

- **タスク実行状態**: `served/getInfo` リクエストの `includeTasks` パラメータにより、現在実行中・最近完了したタスクの一覧を取得可能。各タスクのキュー時間、開始時間、終了時間、CPU使用時間、ステップ数が確認できる（`source/served/extension.d` L1264-1299）
- **ワークスペース状態**: `served/getInfo` リクエストにより、全ワークスペースの初期化状態、選択状態、保留中のエラーを確認可能
- **GCモニタリング**: GC実行のたびにフリーメモリ量、使用メモリ量、GC実行時間をトレースログに出力（`serverbase.d` L487-517）
- **最近終了したFiber履歴**: `FiberManager.recentlyEnded` に最近終了した128件のFiber情報が保持される（`serverbase/source/served/utils/fibermanager.d` L46-47）

### 設定管理

- **ワークスペース設定**: LSPの `workspace/configuration` を使用してクライアントから設定を取得。クライアントが対応していない場合はデフォルト設定で動作（`serverbase/source/served/utils/serverconfig.d`）
- **非標準設定**: `served/didChangeConfiguration` による非標準設定APIに対応し、特殊なエディタ拡張との連携をサポート
- **設定同期タイムアウト**: 初期化後250msのタイムアウトを設けて、クライアントからの設定通知を待機。タイムアウト後は手動で設定をリクエスト（`serverbase/source/served/utils/serverconfig.d` L221）

## 備考

- 本ドキュメントはソースコードの静的解析に基づいて生成されたものであり、プロジェクトの公式要件定義ではない
- 数値目標の多くはコード上の実装値であり、明示的な要件として定義されたものではなく実装上の設計判断である
- serve-dはエディタのサブプロセスとして動作するため、従来のWebサービス向け非機能要件（稼働率SLA、RTO/RPO等）は直接適用されない部分がある
- DCDとの連携ポート（9166）はデフォルト値であり、設定により変更可能である
