# 機能設計書 66-バックグラウンドインデックス

## 概要

本ドキュメントは、serve-dにおけるバックグラウンドインデックス機能の設計を記述する。全ワークスペースのソースコードをバックグラウンドでインデックス化し、シンボル検索・自動インポート等の機能に使用するインデックスを構築・保存する。

### 本機能の処理概要

**業務上の目的・背景**：D言語プロジェクトでのシンボル検索、自動インポート補完、ワークスペースシンボル検索などの機能は、ソースコードのインデックスに依存する。本機能はワークスペースのスタートアップ時にバックグラウンドで全ソースコードをインデックス化し、これらの機能の基盤となるデータを構築する。

**機能の利用シーン**：
- ワークスペーススタートアップ時のDCDサーバー起動後に自動実行
- served/reindexAll通知による手動実行
- プロジェクトの初回オープン時

**主要な処理内容**：
1. 各ワークスペースのインデックス設定が有効か確認する
2. IndexComponentのautoIndexSourcesで標準ライブラリとプロジェクトソースを自動インデックス化する
3. 開いているドキュメントのインデックスを更新する
4. インデクサーの統計情報をログに出力する
5. インデックスをファイルに保存する

**関連システム・外部連携**：workspace-dのIndexComponentを使用。ファイルシステムへのインデックスファイル保存。

**権限による制御**：設定（config.d.enableIndex）によりインデックス機能の有効/無効が制御される。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 3 | ワークスペーススタートアップ | 遷移元 | DCDサーバー起動後にバックグラウンドインデックスを開始する |
| 66 | サーバー情報取得（served/getInfo） | 補助機能 | サーバー情報にモジュールインデックスの内容を含めて返却する |

## 機能種別

データ構築・インデックス化

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| (なし) | - | - | backgroundIndexはパラメータなし | - |
| (なし) | - | - | reindexAllはserved/reindexAll通知としても呼び出し可能 | - |

### 入力データソース

- ワークスペーススタートアップからの内部呼び出し（backgroundIndex）
- LSPクライアントからの `served/reindexAll` 通知（reindexAll）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| (なし) | void | 直接の出力はなし。インデックスデータが内部に構築される |

### 出力先

- IndexComponentの内部データ構造（メモリ上のインデックス）
- ファイルシステム（インデックスファイルの永続化）

## 処理フロー

### 処理シーケンス

```
1. backgroundIndex()が呼び出される
   └─ setImmediate()でreindexAll()を非同期実行
2. reindexAll()の実行
   a. 各ワークスペースのインデックス設定確認
      └─ config.d.enableIndexがfalseならスキップ
   b. 標準ライブラリとプロジェクトソースの自動インデックス化
      └─ indexer.autoIndexSources(stdlib, true)
   c. 開いているドキュメントのインデックス更新
      └─ documents.documentStoreを走査
      └─ D言語ファイルかつインデックス有効なもののみ
      └─ indexer.reindex()で更新
   d. インデクサー統計情報のログ出力
      └─ traceIndexerStats()
   e. インデックスの遅延保存
      └─ delayedSaveIndex()
```

### フローチャート

```mermaid
flowchart TD
    A[backgroundIndex 呼び出し] --> B[setImmediate で reindexAll を非同期実行]
    B --> C{各ワークスペースを走査}
    C -->|次のワークスペース| D{enableIndex 有効?}
    D -->|No| C
    D -->|Yes| E[stdlibPath 取得]
    E --> F[autoIndexSources で自動インデックス化]
    F --> C
    C -->|走査完了| G{開いているドキュメントを走査}
    G -->|次のドキュメント| H{D言語ファイル?}
    H -->|No| G
    H -->|Yes| I{enableIndex 有効?}
    I -->|No| G
    I -->|Yes| J[indexer.reindex でインデックス更新]
    J --> G
    G -->|走査完了| K{各ワークスペースを走査}
    K -->|次| L[traceIndexerStats で統計出力]
    L --> M[delayedSaveIndex で遅延保存]
    M --> K
    K -->|走査完了| N[完了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-66-01 | インデックス有効チェック | config.d.enableIndexがfalseのワークスペースはスキップ | 常時 |
| BR-66-02 | D言語ファイル限定 | インデックス対象はD言語ファイル（getLanguageId == "d"）のみ | ドキュメント走査時 |
| BR-66-03 | 遅延保存 | インデックスの保存は2500ms遅延で実行される | 常時 |
| BR-66-04 | 非同期実行 | backgroundIndexはsetImmediateで非同期的にreindexAllを呼び出す | 常時 |
| BR-66-05 | GC最適化 | 統計情報出力時にGC.collect()とGC.minimize()を実行 | traceIndexerStats内 |

### 計算ロジック

特になし。

## データベース操作仕様

### 操作別データベース影響一覧

データベース操作はない。IndexComponentの内部データ構造とファイルシステムのインデックスファイルを使用。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | インデックスファイル保存失敗 | ファイルシステム書き込みエラー | IndexComponent内部でハンドリング |

### リトライ仕様

delayedSaveIndexで2500ms遅延により、連続的なインデックス更新による頻繁な保存を回避する。

## トランザクション仕様

トランザクション管理は不要。

## パフォーマンス要件

- setImmediateによる非同期実行でUIブロッキングを回避
- delayedSaveIndexで保存頻度を制御（2500msデバウンス）
- GC.collect()/GC.minimize()でメモリ最適化

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

ソースコードの読み取りとインデックスファイルの書き込みのみ。

## 備考

- backgroundIndex()は内部関数（LSPメソッド/通知ではない）
- reindexAll()は `@protocolNotification("served/reindexAll")` で外部からも呼び出し可能
- インデクサー統計にはfailedFiles, indexedModules, numDefinitions, numImportsが含まれる

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | index.d | `source/served/commands/index.d` | IndexComponent型とreindexChangeTimeout変数（71行目） |

**読解のコツ**: `setImmediate` はファイバーベースの非同期実行ユーティリティ。`getYield()` はFutureの結果をファイバー内で待機する。`clearTimeout`/`setTimeout` はJavaScript風のタイマーAPI。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | index.d | `source/served/commands/index.d` | backgroundIndex関数（16-21行目） |

**主要処理フロー**:
1. **17-19行目**: setImmediate内でreindexAll()を呼び出し

#### Step 3: reindexAll処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | index.d | `source/served/commands/index.d` | reindexAll関数（23-69行目） |

**主要処理フロー**:
1. **26-37行目**: 各ワークスペースの自動インデックス化（autoIndexSources）
2. **39-54行目**: 開いているドキュメントのインデックス更新
3. **56-68行目**: 統計情報出力とインデックス保存

#### Step 4: ヘルパー関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | index.d | `source/served/commands/index.d` | delayedSaveIndex関数（117-123行目） - 遅延保存 |
| 4-2 | index.d | `source/served/commands/index.d` | traceIndexerStats関数（125-137行目） - 統計情報出力 |

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

```
backgroundIndex() [index.d:16-21]
    |
    +-- setImmediate()
        |
        +-- reindexAll() [index.d:23-69]
            |
            +-- [各ワークスペース] indexer.autoIndexSources(stdlib, true)
            |       +-- IndexComponent (workspace-d内部)
            |
            +-- [各ドキュメント] indexer.reindex(filePath, now, ...)
            |       +-- IndexComponent (workspace-d内部)
            |
            +-- traceIndexerStats(indexer) [index.d:125-137]
            |       +-- GC.collect() / GC.minimize()
            |       +-- indexer.getHealth()
            |
            +-- delayedSaveIndex(indexer) [index.d:117-123]
                    +-- setTimeout(2500ms)
                    +-- indexer.saveIndex()
```

### データフロー図

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

ワークスペーススタートアップ ──▶  backgroundIndex()             ──▶  インデックスデータ（メモリ）
served/reindexAll通知     ──▶  reindexAll()                        インデックスファイル（ディスク）
                                |                                    ログ（統計情報）
ソースコード（ファイル）     ──▶  autoIndexSources()
開いているドキュメント      ──▶  reindex()
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| index.d | `source/served/commands/index.d` | ソース | backgroundIndex, reindexAll関数の定義（全138行） |
| extension.d | `source/served/extension.d` | ソース | ワークスペーススタートアップからの呼び出し元 |
| types.d | `source/served/types.d` | ソース | ワークスペース設定（enableIndex） |
| async.d | `source/served/utils/async.d` | ソース | setImmediate, setTimeout等の非同期ユーティリティ |
