# 通知設計書 10-プリコンパイルキャッシュ生成失敗警告

## 概要

本ドキュメントは、Juliaランタイムにおけるプリコンパイルキャッシュ生成失敗警告通知の設計を記述する。`compilecache`の呼び出しが使用可能なプリコンパイルキャッシュファイルの生成に失敗した場合に警告ログを出力する。

### 本通知の処理概要

**業務上の目的・背景**：Juliaのプリコンパイルシステムは、パッケージの初回ロード時にコンパイル結果をキャッシュファイル（`.ji`ファイル）として保存し、以降のロードを高速化する。`compilecache`の呼び出しが失敗した場合、またはキャッシュファイルは生成されたがデシリアライズに失敗した場合、パッケージは通常のインクルード方式でロードされる。本通知はこの失敗を開発者に警告し、パッケージのロードパフォーマンスへの影響を伝える。

**通知の送信タイミング**：`_require`関数内で、`compilecache`の呼び出し後に2つの条件で発生する。(1) `compilecache`が例外を返した場合（プリコンパイル不可エラー以外）、(2) キャッシュファイルは生成されたが`_tryrequire_from_serialized`でのロードに失敗した場合。

**通知の受信者**：Juliaプログラムを実行している開発者。ログメッセージとして標準エラー出力（または設定されたログハンドラ）に出力される。

**通知内容の概要**：「The call to compilecache failed to create a usable precompiled cache file for {pkg}」というメッセージが`@warn`マクロにより出力される。発生した例外が`exception`キーワード引数として付随する。

**期待されるアクション**：開発者はパッケージのプリコンパイルエラーの原因を調査する。キャッシュファイルの破損、依存関係の不整合、メモリ不足などが考えられる。`Pkg.precompile()`の手動実行や、キャッシュファイルの削除（`~/.julia/compiled`の該当ディレクトリ）を試みる。

## 通知種別

ログ出力（Warnレベル） - Juliaの`@warn`マクロによるロギングシステム経由の警告通知

## 送信仕様

### 基本情報

| 項目 | 内容 |
|-----|------|
| 送信方式 | 同期（`_require`関数内で即座に出力） |
| 優先度 | 中（パフォーマンスに影響するが機能的にはフォールバックにより動作する） |
| リトライ | 無し（ただし次回のパッケージロード時に再度プリコンパイルが試行される） |

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

Juliaのロギングフレームワーク（`CoreLogging`）に委譲される。デフォルトでは`stderr`に出力される。

## 通知テンプレート

### メール通知の場合

該当なし（ログ出力のみ）

### 本文テンプレート

```
┌ Warning: The call to compilecache failed to create a usable precompiled cache file for MyPackage [1234-5678-...]
│   exception =
│    ErrorException("...")
│    Stacktrace:
│     [1] ...
└ @ Base loading.jl:2912
```

### 添付ファイル

該当なし

## テンプレート変数

| 変数名 | 説明 | データ取得元 | 必須 |
|--------|------|-------------|-----|
| pkg | パッケージの表示名 | `repr("text/plain", pkg)` | Yes |
| exception/loaded | 発生した例外またはロード失敗の結果 | `compilecache`の返り値または`_tryrequire_from_serialized`の返り値 | Yes |

## 送信トリガー・条件

### トリガー一覧

| トリガー種別 | トリガーイベント | 送信条件 | 説明 |
|------------|----------------|---------|------|
| API呼び出し | `compilecache`が例外を返した | `isa(loaded, Exception) && !precompilableerror(loaded)` | プリコンパイル非対応（`__precompile__(false)`）以外のエラー |
| API呼び出し | `_tryrequire_from_serialized`が失敗 | `!isa(loaded, Module)` | キャッシュファイルは生成されたがデシリアライズに失敗 |

### 送信抑止条件

| 条件 | 説明 |
|-----|------|
| プリコンパイル成功 | `compilecache`と`_tryrequire_from_serialized`が正常に完了した場合 |
| `precompilableerror(loaded)` | `__precompile__(false)`によるプリコンパイル非対応は意図的であるため通知しない |
| `use_compiled_modules != 1` | コンパイルモジュールが無効な場合はプリコンパイル自体が試行されない |

## 処理フロー

### 送信フロー

```mermaid
flowchart TD
    A["_require(pkg)"] --> B["compilecache(pkg, spec)"]
    B --> C{戻り値の型は?}
    C -->|Nothing| D["goto load_from_cache"]
    C -->|Exception| E{precompilableerror?}
    E -->|Yes| F[ログなし - 意図的な非対応]
    E -->|No| G["@warn compilecache failed (1回目)"]
    C -->|"Tuple{String,String}"| H["_tryrequire_from_serialized"]
    H --> I{Moduleを返した?}
    I -->|Yes| J[成功 - return]
    I -->|No| K["@warn compilecache failed (2回目)"]
    G --> L[通常ロードへフォールバック]
    K --> L
    F --> L
```

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

### 参照テーブル一覧

該当なし（ファイルシステムのキャッシュファイルを参照する）

### 更新テーブル一覧

該当なし（キャッシュファイルの生成が試行される）

## エラー処理

### エラーケース一覧

| エラー種別 | 発生条件 | 対処方法 |
|----------|---------|---------|
| compilecacheエラー | プリコンパイルプロセスが失敗 | 警告出力後、通常のファイルロードにフォールバック |
| デシリアライズエラー | キャッシュファイルの読み込みに失敗 | 警告出力後、通常のファイルロードにフォールバック |
| PrecompilableError（インクリメンタル時） | インクリメンタルプリコンパイル中の失敗 | 例外をスローしてプリコンパイルを中止（2924-2927行目） |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | 0（同一セッション内。ただし次回起動時に再試行される） |
| リトライ間隔 | - |
| リトライ対象エラー | - |

## 配信設定

### レート制限

| 項目 | 内容 |
|-----|------|
| 制限 | なし（失敗したパッケージごとに出力） |

### 配信時間帯

制限なし

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

例外のバックトレースにファイルパスやパッケージ内部の構造が含まれる可能性がある。本番環境ではログの出力先管理に注意が必要である。

## 備考

- 本通知は同一の`_require`関数内の2箇所（2912行目と2919行目）で発生する可能性がある
- `maybe_cachefile_lock`によりプリコンパイルの並行実行が制御される（2860行目）
- `isinteractive()`の場合はInfoレベル、そうでない場合はDebugレベルで「Precompiling...」メッセージが出力される（2865-2866行目）
- インクリメンタルプリコンパイル中（`JLOptions().incremental != 0`）は失敗時に`PrecompilableError`がスローされる（2924-2927行目）
- `loadable_exts`パラメータにより拡張機能の同時プリコンパイルが制御される（2899行目）

---

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

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

### 推奨読解順序

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

プリコンパイルキャッシュの管理構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | loading.jl | `base/loading.jl` | `PkgId`型、`CacheFlags`、キャッシュファイルのパス規則 |

**読解のコツ**: プリコンパイルキャッシュファイルは`DEPOT_PATH`の`compiled`サブディレクトリに保存される。`.ji`ファイルがシリアライズされたモジュールデータ、`.so`/`.dll`がネイティブコードキャッシュである。

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

通知が発生する箇所を確認する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | loading.jl | `base/loading.jl` | `_require`関数内のcompilecache呼び出しと結果処理（2856-2928行目） |

**主要処理フロー**:
1. **2860行目**: `maybe_cachefile_lock`でキャッシュファイルのロックを取得
2. **2862行目**: ロック取得後にキャッシュを再検索（ダブルチェック）
3. **2866行目**: 「Precompiling...」ログ出力
4. **2899行目**: `compilecache(pkg, spec; loadable_exts)`を実行
5. **2908行目**: `isa(loaded, Exception)`の場合、プリコンパイルエラーかチェック
6. **2912行目**: プリコンパイル非対応でないエラーの場合、`@warn`を出力（1つ目）
7. **2916行目**: キャッシュファイルが生成された場合、`_tryrequire_from_serialized`でロード試行
8. **2918-2919行目**: ロードに失敗した場合、`@warn`を出力（2つ目）
9. **2924-2927行目**: インクリメンタル時は`PrecompilableError`をスロー

#### Step 3: compilecache関数を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | loading.jl | `base/loading.jl` | `compilecache`関数の定義 - プリコンパイルプロセスの実行 |

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

```
using/import パッケージ
    |
    +-- require(pkg)
        |
        +-- _require(pkg)  [base/loading.jl]
            |
            +-- maybe_cachefile_lock(pkg, spec.path) do
            |   |
            |   +-- _require_search_from_serialized (ダブルチェック)
            |   +-- compilecache(pkg, spec; loadable_exts)
            |       |
            |       +-- (Exception) precompilableerror チェック
            |       |   +-- (!precompilable) @warn "compilecache failed"  [2912行目]
            |       |
            |       +-- (Tuple) _tryrequire_from_serialized
            |           +-- (!Module) @warn "compilecache failed"  [2919行目]
            |
            +-- (incremental) throw(PrecompilableError())  [2926行目]
            +-- (非incremental) 通常のファイルロードへ
```

### データフロー図

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

PkgId + PackageSpec ────> compilecache                    ──> キャッシュファイル (.ji)
                           |                               ──> Module (成功時)
                           +-- プリコンパイルプロセス
                           |
                           +-- _tryrequire_from_serialized
                           |   +-- デシリアライズ
                           |
                           +-- (失敗時) @warn ──> stderr
                           +-- 通常ロードにフォールバック
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| loading.jl | `base/loading.jl` | ソース | パッケージロード、プリコンパイルキャッシュ管理の全実装 |
