# 通知設計書 9-exit

## 概要

本ドキュメントは、LSP(Language Server Protocol)におけるexit通知の設計仕様を記載する。クライアントからサーバーへ送信される通知であり、サーバーに終了を通知する。

### 本通知の処理概要

exit通知は、クライアントがサーバーにプロセス終了を要求する際に送信される通知である。通常、shutdownリクエストの後に送信され、サーバープロセスの正常終了をトリガーする。

**業務上の目的・背景**：LSPのライフサイクルにおいて、サーバープロセスは明示的な終了通知を受けるまで動作を継続する。exit通知により、サーバーはリソースを適切にクリーンアップし、プロセスを正常終了させることができる。これにより、リソースリーク（メモリ、ファイルハンドル等）を防ぎ、システムの安定性を維持する。

**通知の送信タイミング**：クライアントがshutdownリクエストを送信し、そのレスポンスを受信した後に送信される。shutdownリクエスト前にexit通知を送信することはLSP仕様違反であり、サーバーは終了コード1で終了すべきとされている。

**通知の受信者**：clojure-lspサーバープロセスがこの通知を受信する。

**通知内容の概要**：通知にはパラメータが含まれない。

**期待されるアクション**：サーバーは受信後、以下の処理を順次実行する。(1) サーバーのシャットダウン（未処理メッセージの完了待機、最大10秒）、(2) エージェントのシャットダウン、(3) System/exit 0でプロセス終了。

## 通知種別

LSP通知 (クライアント → サーバー)

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（即座にプロセス終了） |
| 優先度 | 最高（ライフサイクル終了） |
| リトライ | なし（通知のため応答なし） |

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

クライアントからサーバーへの一方向通知のため、送信先決定ロジックは不要。

## 通知テンプレート

### パラメータ構造

| 項目 | 内容 |
|-----|------|
| メソッド名 | exit |
| パラメータ型 | なし |
| プロトコル | JSON-RPC 2.0 over stdio |

### パラメータ定義

```json
{}
```

または（パラメータ省略可能）

### 添付ファイル

該当なし（LSP通知にファイル添付機能なし）

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| なし | パラメータなし | - | - |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| ライフサイクル | エディタ終了 | shutdown完了後 | ユーザーがエディタを閉じた時 |
| ライフサイクル | LSP再起動 | shutdown完了後 | LSPの再起動要求時 |
| 異常終了 | クライアント異常 | shutdown未完了 | クライアントの異常終了時（非推奨） |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| shutdown未送信 | shutdownリクエストが送信されていない場合（仕様違反だが処理は実行される） |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[shutdownレスポンス受信] --> B[exit通知送信]
    B --> C[サーバーで受信]
    C --> D[exit関数を呼び出し]
    D --> E[jsonrpc.server/shutdown]
    E --> F{未処理メッセージ?}
    F -->|あり| G[最大10秒待機]
    F -->|なし| H[shutdown-agents]
    G --> H
    H --> I[System/exit 0]
```

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

### 参照テーブル一覧

該当なし（終了処理のため参照不要）

### 更新テーブル一覧

該当なし（終了処理のため更新不要）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| シャットダウンタイムアウト | 未処理メッセージが10秒以内に完了しない | 強制終了 |
| shutdown未実行 | shutdownリクエストなしでexit | 終了コード1で終了すべき（仕様）、clojure-lspは終了コード0で終了 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（通知のためリトライなし） |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 送信回数 | セッションあたり1回のみ |
| 1分あたり上限 | N/A |
| 1日あたり上限 | N/A |

### 配信時間帯

制限なし（終了時に1回のみ）

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

- exit通知によりサーバープロセスが終了するため、不正なexit通知はサービス拒否（DoS）攻撃となりうる
- 正規のLSPクライアントのみがexit通知を送信できることを前提とする

## 備考

- LSP仕様: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#exit
- この通知は応答を返さない(notification)
- shutdownリクエストの後に送信されるべきであり、shutdown前の送信は仕様違反
- System/exit 0が呼び出されるため、この通知以降の処理は実行されない

---

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

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

### 推奨読解順序

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

まず、プログラム間で受け渡されるデータ構造を理解することが重要である。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | なし | - | exit通知にパラメータはない |

**読解のコツ**: exit通知はパラメータがないため、処理フローの理解に集中すること。

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

処理の起点となるファイル・関数を特定する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | server.clj | `cli/src/clojure_lsp/server.clj` | receive-notification multimethod定義 |

**主要処理フロー**:
1. **579-580行目**: `exit`メソッドのdefmethod定義
2. **580行目**: exit関数の呼び出し

#### Step 3: 終了処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | server.clj | `cli/src/clojure_lsp/server.clj` | exit関数の定義 |

**主要処理フロー**:
- **542-547行目**: exit関数本体
- **545行目**: jsonrpc.server/shutdownの呼び出し（最大10秒待機）
- **546行目**: shutdown-agentsの呼び出し
- **547行目**: System/exit 0の呼び出し

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

```
jsonrpc.server/receive-notification "exit"
    |
    +-- server.clj (579-580行目)
           |
           +-- exit (server.clj 542-547行目)
                  |
                  +-- shared/logging-task :lsp/exit
                  |
                  +-- jsonrpc.server/shutdown (545行目)
                  |      |
                  |      +-- 未処理メッセージの完了待機（最大10秒）
                  |
                  +-- shutdown-agents (546行目)
                  |      |
                  |      +-- Clojureエージェントのシャットダウン
                  |
                  +-- System/exit 0 (547行目)
                         |
                         +-- JVMプロセス終了
```

### データフロー図

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

exit通知 (パラメータなし)
    |
    v
receive-notification "exit"
    |
    v
exit関数
    |
    +---> logging-task :lsp/exit (ログ記録)
    |
    +---> jsonrpc.server/shutdown
    |           |
    |           +---> 未処理メッセージの完了待機
    |           |           (最大10秒、ブロッキング)
    |           |
    |           v
    +---> shutdown-agents
    |           |
    |           +---> Clojureエージェントシャットダウン
    |           |
    |           v
    +---> System/exit 0
                |
                v
          JVMプロセス終了（終了コード0）
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| server.clj | `cli/src/clojure_lsp/server.clj` | ソース | LSPサーバーのエントリーポイント、通知受信、終了処理 |
| shared.clj | `lib/src/clojure_lsp/shared.clj` | ソース | logging-taskマクロ |
