# 通知設計書 16-循環依存除外警告

## 概要

本ドキュメントは、Juliaのプリコンパイルシステムにおいて循環依存が検出され、該当パッケージがプリコンパイル対象から除外された場合に発行される警告通知の設計仕様を記述する。

### 本通知の処理概要

本通知は、`Precompilation`モジュールのパッケージプリコンパイル処理において、パッケージ間の依存関係グラフに循環依存（サイクル）が検出された場合に、影響を受けるパッケージを列挙して警告を発行する処理である。

**業務上の目的・背景**：Juliaのプリコンパイルシステムはパッケージの依存関係に基づいて順序付けられた並列プリコンパイルを実行する。循環依存が存在すると正しいプリコンパイル順序を決定できないため、該当するパッケージ群をプリコンパイル対象から除外する必要がある。本警告は、除外されたパッケージとその理由（循環依存の構造）をユーザーに通知し、パッケージ構成の見直しを促すために存在する。これにより、ロード時間の最適化が妨げられている原因を開発者が特定できる。

**通知の送信タイミング**：`Precompilation`モジュールのプリコンパイル実行関数内で、依存関係グラフのサイクル検出（SCC的アルゴリズム）が完了した後、`circular_deps`リストが空でない場合に送信される。

**通知の受信者**：パッケージのプリコンパイルを実行しているユーザー（`using`時の自動プリコンパイルまたは`Pkg.precompile()`の手動実行時）。標準エラー出力を通じてログ表示される。

**通知内容の概要**：`excluded_circular_deps_explanation`関数により生成される詳細なメッセージが出力される。循環依存のサイクル構造をASCIIアートの罫線で可視化し、影響を受けるすべてのパッケージを列挙する。拡張機能（Extension）の場合は「親パッケージ → 拡張機能名」形式で表示される。

**期待されるアクション**：パッケージ開発者は、報告されたサイクルに含まれるパッケージ間の依存関係を見直す。必要に応じて、依存関係を弱依存（weakdeps）に変更するか、パッケージの分割・再構成を検討する。

## 通知種別

ログ（Warn） - Juliaの標準ログシステム（`@warn`マクロ）を通じたコンソール警告出力

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（`@warn`マクロによる即座のログ出力） |
| 優先度 | 高（プリコンパイルの最適化に直接影響） |
| リトライ | なし |

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

Juliaの標準ロギングフレームワーク（`CoreLogging`）を通じて、現在アクティブなロガーに送信される。IOContext付きの出力先に送信され、カラー設定が反映される。

## 通知テンプレート

### メール通知の場合

該当なし（コンソールログ出力のみ）

### 本文テンプレート

```
Warning: Circular dependency detected.
    Precompilation will be skipped for dependencies in this cycle:
     ┌ {パッケージA}
     │ {パッケージB}
     └─ {パッケージC}
    Precompilation will also be skipped for the following, which depend on the above cycle:
      {パッケージD}
      {パッケージE}
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| cycles | 検出された循環依存のサイクルリスト | `scan_pkg!/scan_deps!`による依存関係グラフ走査 | Yes |
| circular_deps | サイクルに影響されるすべてのパッケージ | 依存関係グラフのトランジティブ解析 | Yes |
| ext_to_parent | 拡張機能と親パッケージのマッピング | プリコンパイルシステムの構成情報 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| パッケージプリコンパイル | プリコンパイル処理の依存関係解析 | `!isempty(circular_deps)` | 循環依存が検出されたパッケージが存在する場合 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| 循環依存なし | `circular_deps`が空の場合、警告は発行されない |
| serial_deps | シリアル依存として指定されたパッケージはスキャン対象外 |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A[プリコンパイル処理開始] --> B[依存関係グラフ構築]
    B --> C[各パッケージについてscan_pkg!実行]
    C --> D{サイクル検出?}
    D -->|Yes| E[circular_depsに追加]
    D -->|No| F[次のパッケージへ]
    E --> G[影響パッケージのイベント通知]
    F --> C
    G --> C
    C -->|全パッケージ走査完了| H{circular_depsが空?}
    H -->|空| I[プリコンパイル続行]
    H -->|非空| J[excluded_circular_deps_explanation生成]
    J --> K["@warn メッセージ出力"]
    K --> I
```

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

### 参照テーブル一覧

該当なし（データベースを使用しない。パッケージの依存関係はManifest.tomlから取得）

### 更新テーブル一覧

該当なし（データベースを使用しない）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| 該当なし | 循環依存の検出自体はエラーではなく警告として処理 | プリコンパイルから除外し処理を続行 |

### リトライ仕様

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

## 配信設定

### レート制限

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

### 配信時間帯

制限なし（プリコンパイル処理の実行時に随時発行）

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

通知にはパッケージ名とUUIDが含まれるが、セキュリティ上の機密情報は含まれない。

## 備考

- `scan_pkg!`と`scan_deps!`はSCC（強連結成分）的なアルゴリズムでサイクルを検出する
- 複数のサイクルが存在する場合、すべてのサイクルが個別に表示される
- 拡張機能（Extension）は「親 → 拡張名」形式で`full_name`関数により表示される
- サイクルの可視化にはASCII罫線文字（┌│└─）が使用され、カラー出力が有効な場合は`light_black`色が適用される
- `plural1`/`plural2`変数により、サイクル数に応じた適切な単数形/複数形が使用される

---

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

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

### 推奨読解順序

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

プリコンパイルシステムの依存関係管理構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | precompilation.jl | `base/precompilation.jl` | `ExplicitEnv`構造体（9-27行目）- パッケージ依存関係の格納 |
| 1-2 | precompilation.jl | `base/precompilation.jl` | `PkgConfig`型（381行目）- パッケージとコンフィグのペア |

**読解のコツ**: `direct_deps`はパッケージの直接依存関係のマッピングで、`Dict{PkgId, Vector{PkgId}}`型。これがサイクル検出のグラフとして使用される。

#### Step 2: サイクル検出アルゴリズムを理解する

`scan_pkg!`/`scan_deps!`によるサイクル検出ロジックを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | precompilation.jl | `base/precompilation.jl` | `scan_pkg!`（428-434行目）- キャッシュ付きサイクル検出のエントリーポイント |
| 2-2 | precompilation.jl | `base/precompilation.jl` | `scan_deps!`（435-449行目）- スタックベースの深さ優先探索 |

**主要処理フロー**:
1. **436行目**: `push!(stack, pkg)` - 現在のパッケージをスタックに追加
2. **438行目**: `for dep in dmap[pkg]` - 各依存パッケージを走査
3. **439行目**: `if dep in stack` - スタック内に依存先が存在すればサイクル
4. **441行目**: `cycle' = stack[findlast(==(dep), stack):end]` - 最小サイクルの抽出

#### Step 3: 警告メッセージ生成を理解する

`excluded_circular_deps_explanation`関数の構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | precompilation.jl | `base/precompilation.jl` | `excluded_circular_deps_explanation`（392-425行目）- メッセージ構築ロジック |
| 3-2 | precompilation.jl | `base/precompilation.jl` | `full_name`（384-390行目）- 拡張機能名の表示 |

**主要処理フロー**:
- **393行目**: サイクル外の依存パッケージを分離
- **395-413行目**: 各サイクルのASCII罫線表示を構築
- **417-424行目**: メッセージ全体の組み立て（サイクルメンバーと影響パッケージ）

#### Step 4: 警告の発行箇所を理解する

プリコンパイル本体処理内での`@warn`呼出しを理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | precompilation.jl | `base/precompilation.jl` | 793-817行目のサイクル検出とイベント通知ループ |

**主要処理フロー**:
- **794行目**: `cycles = Vector{Base.PkgId}[]` - サイクル格納リスト初期化
- **805-814行目**: 各パッケージのサイクル検出と`was_processed`イベント通知
- **816-817行目**: `@warn excluded_circular_deps_explanation(...)` - 警告発行

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

```
[プリコンパイル処理]                     [base/precompilation.jl]
    |
    +-- scan_pkg!(stack, could_be_cycle, cycles, pkg, direct_deps)  [428]
    |       |
    |       +-- scan_deps!(stack, could_be_cycle, cycles, pkg, dmap) [435]
    |               |
    |               +-- [再帰呼出し] scan_pkg!
    |
    +-- excluded_circular_deps_explanation(io, ext_to_parent, circular_deps, cycles) [392]
    |       |
    |       +-- full_name(ext_to_parent, pkg)                        [384]
    |       +-- _color_string(line, :light_black, hascolor)
    |
    +-- @warn [メッセージ出力]                                        [817]
```

### データフロー図

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

direct_deps (Dict)         --> scan_pkg!/scan_deps!        --> cycles, circular_deps
                                [precompilation.jl:805-814]

cycles, circular_deps      --> excluded_circular_deps_     --> 警告メッセージ文字列
ext_to_parent                   explanation
                                [precompilation.jl:392]

警告メッセージ文字列       --> @warn                       --> stderr出力
                                [precompilation.jl:817]
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| precompilation.jl | `base/precompilation.jl` | ソース | Precompilationモジュール全体、循環依存検出と警告 |
| loading.jl | `base/loading.jl` | ソース | パッケージロードシステム（PkgId等の型定義） |
| logging.jl | `base/logging.jl` | ソース | `@warn`マクロの定義 |
