# バッチ設計書 6-tooling/print-cache-file.js

## 概要

本ドキュメントは、キャッシュファイルの内容表示スクリプト `tooling/print-cache-file.js` の設計仕様を定義するものである。webpackのシリアライゼーション機構を利用してpackファイルをデシリアライズし、構造化されたデータを人間可読形式で出力する。

### 本バッチの処理概要

`tooling/print-cache-file.js` は、webpackが生成するキャッシュファイル（.packファイル）の内容を人間が読める形式で標準出力に表示するユーティリティスクリプトである。webpackの内部シリアライゼーション機構（BinaryMiddleware、FileMiddleware、Serializer）を利用してキャッシュデータをデシリアライズし、階層構造を持つデータをインデント付きで表示する。

**業務上の目的・背景**：webpackのpersistent caching機能はビルドパフォーマンスを大幅に改善するが、キャッシュファイルはバイナリ形式であり直接読むことができない。デバッグや問題調査の際にキャッシュの内容を確認する必要がある場合に、このスクリプトでキャッシュの構造と内容を可視化できる。キャッシュの破損やサイズ肥大化の原因調査に有用である。

**バッチの実行タイミング**：キャッシュファイルの内容確認が必要な際に、開発者が手動でコマンドラインから実行する。

**主要な処理内容**：
1. コマンドライン引数で指定されたキャッシュファイルのパスを取得する
2. rawSerializer（FileMiddleware）でファイルを読み込み、データサイズ情報を集計する
3. serializer（BinaryMiddleware + FileMiddleware）でファイルをデシリアライズする
4. デシリアライズされたデータを再帰的に走査し、各要素の型に応じてフォーマットして出力する
5. 遅延読み込み（lazy）データのサイズ情報（MiB単位）を表示する
6. 参照カウントの上位10件のサマリーを出力する

**前後の処理との関連**：独立したユーティリティスクリプトであり、他のバッチやnpmスクリプトとの直接的な依存関係はない。webpackのpersistent caching機能が生成したキャッシュファイルを入力として使用する。

**影響範囲**：読み取り専用のスクリプトであり、入力ファイルやその他のファイルに変更を加えない。標準出力にのみ結果を出力する。

## バッチ種別

ユーティリティ / デバッグ支援 / データ解析

## 実行スケジュール

| 項目 | 内容 |
|-----|------|
| 実行頻度 | 随時（必要に応じて手動実行） |
| 実行時刻 | 任意 |
| 実行曜日 | N/A |
| 実行日 | N/A |
| トリガー | 手動（コマンドラインから実行） |

## 実行条件

### 前提条件

| 条件 | 説明 |
|-----|------|
| Node.jsランタイム | Node.jsがインストールされていること |
| webpackライブラリ | webpackの内部モジュール（serialization系）がrequire可能であること |
| キャッシュファイル | webpackが生成した.packファイルが存在すること |

### 実行可否判定

特別な実行可否判定ロジックはない。ファイルが存在しない場合やフォーマットが不正な場合はデシリアライズ処理でエラーが発生する。

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | デフォルト値 | 説明 |
|-------------|-----|-----|-------------|------|
| process.argv[2] | string | Yes | なし | キャッシュファイル（.pack）のパス |

### 入力データソース

| データソース | 形式 | 説明 |
|-------------|------|------|
| .packファイル | バイナリ | webpackのpersistent cachingが生成したキャッシュファイル |

## 出力仕様

### 出力データ

| 出力先 | 形式 | 説明 |
|-------|------|------|
| 標準出力（stdout） | テキスト | キャッシュファイルの構造化データを人間可読形式で表示 |

### 出力ファイル仕様

ファイル出力は行わない。全ての結果は標準出力に出力される。

## 処理フロー

### 処理シーケンス

```
1. コマンドライン引数からファイルパスを取得
   └─ process.argv[2] を使用
2. rawSerializerでファイルを読み込み、サイズ情報を集計
   └─ FileMiddlewareのみでデシリアライズ
   └─ captureSize関数で各データ要素のサイズとlazy部分のサイズを再帰的に計算
   └─ サイズ情報をMiB単位で表示（直接サイズ + 遅延サイズ）
3. serializerで本格的なデシリアライズ
   └─ BinaryMiddleware + FileMiddlewareでデシリアライズ
4. printData関数で再帰的にデータを表示
   └─ バージョン番号の表示
   └─ ESCAPE制御コードの解釈
      └─ ESCAPE_ESCAPE_VALUE (null): "null"と表示
      └─ ESCAPE_UNDEFINED (false): "undefined"と表示
      └─ ESCAPE_END_OBJECT (true): オブジェクトの終了、参照番号を割り当て
      └─ 負数: 既存オブジェクトへの参照
      └─ 数値: 型参照によるオブジェクト開始
      └─ 文字列: 新しい型のオブジェクト開始（型名とリクエスト名を登録）
   └─ 文字列値の表示（空でない場合は参照番号を割り当て）
   └─ Bufferの16進数表示
   └─ lazy関数の再帰的展開（lazy-fileまたはlazy-inline）
5. サマリー出力
   └─ 参照カウントの上位10件を表示
```

### フローチャート

```mermaid
flowchart TD
    A[バッチ開始] --> B[コマンドライン引数からファイルパス取得]
    B --> C[rawSerializerでサイズ情報集計]
    C --> D[サイズ情報表示]
    D --> E[serializerでデシリアライズ]
    E --> F[printDataで再帰的にデータ表示]
    F --> G{データ要素の型}
    G -->|Buffer| H[16進数表示]
    G -->|ESCAPE| I[制御コード解釈]
    G -->|string| J[文字列表示 + 参照番号割当]
    G -->|function lazy| K[遅延データ展開・再帰表示]
    G -->|その他| L[文字列変換表示]
    H --> M{次の要素あり?}
    I --> M
    J --> M
    K --> M
    L --> M
    M -->|Yes| G
    M -->|No| N[参照カウントサマリー出力]
    N --> O[バッチ終了]
```

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

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

本バッチはデータベースを操作しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| Error | デシリアライズ失敗 | キャッシュファイルが破損または互換性のないバージョンの場合 | webpackのバージョンを確認し、キャッシュを再生成 |
| ENOENT | ファイル未検出 | 指定されたファイルが存在しない | 正しいファイルパスを指定して再実行 |
| Error | データ形式エラー | "Not an array"（データがArray形式でない場合） | キャッシュファイルの整合性を確認 |

### リトライ仕様

| 項目 | 内容 |
|-----|------|
| リトライ回数 | なし |
| リトライ間隔 | N/A |
| リトライ対象エラー | N/A（リトライ機構は未実装） |

### 障害時対応

デシリアライズに失敗した場合は、webpackのバージョンとキャッシュファイルの互換性を確認する。キャッシュの再生成（キャッシュディレクトリの削除後にビルドを再実行）を行う。

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

| 項目 | 内容 |
|-----|------|
| トランザクション範囲 | N/A（データベース操作なし） |
| コミットタイミング | N/A |
| ロールバック条件 | N/A |

## パフォーマンス要件

| 項目 | 内容 |
|-----|------|
| 想定処理件数 | 1ファイル |
| 目標処理時間 | キャッシュファイルのサイズに依存（大規模プロジェクトでは数秒〜数十秒） |
| メモリ使用量上限 | キャッシュファイル全体をメモリに展開するため、キャッシュサイズに比例 |

## 排他制御

排他制御は行わない。読み取り専用のため、他のプロセスとの排他は不要。ただし、webpackビルド中にキャッシュファイルが更新されている場合は、不完全な内容を読み取る可能性がある。

## ログ出力

| ログ種別 | 出力タイミング | 出力内容 |
|---------|--------------|---------|
| データ表示 | デシリアライズ完了後 | キャッシュファイルの全構造化データ（インデント付き） |
| サイズ情報 | ファイル読み込み後 | ファイルの直接サイズとlazy部分のサイズ（MiB単位） |
| サマリー | データ表示完了後 | 参照カウント上位10件 |

## 監視・アラート

| 監視項目 | 閾値 | アラート先 |
|---------|-----|----------|
| N/A | N/A | N/A（監視設定は未実装） |

## 備考

- webpackの内部モジュール（BinaryMiddleware、FileMiddleware、Serializer、SerializerMiddleware）を直接使用するため、webpackのバージョン変更により動作しなくなる可能性がある
- サイズ情報は MiB（メビバイト = 1,048,576バイト）単位で小数点以下2桁まで表示される
- lazy-fileとlazy-inlineの2種類の遅延読み込みを区別して表示する
  - lazy-file: BinaryMiddlewareによる遅延でないもの（ファイル分割による遅延）
  - lazy-inline: BinaryMiddlewareによる遅延（インラインの遅延展開）
- オブジェクトの参照システムを実装しており、重複データの参照関係を追跡する
- 参照カウントサマリーでは `refCounters.slice(10)` により上位10件以降を表示するが、これはコードの意図としては上位10件を表示する想定と思われる（潜在的なバグの可能性）
- コマンドライン引数でファイルパスを指定して使用する
