# 機能設計書 45-cacheLife

## 概要

本ドキュメントは、Next.jsの`cacheLife()`関数の設計を記述する。`"use cache"`関数内でキャッシュのライフタイム（stale, revalidate, expire）を制御するAPIである。

### 本機能の処理概要

**業務上の目的・背景**：`"use cache"`ディレクティブでキャッシュされた関数やコンポーネントのキャッシュ期間を、ビジネス要件に応じてきめ細かく制御する必要がある。`cacheLife()`は、プロファイル名（`"seconds"`, `"minutes"`, `"hours"`, `"days"`, `"weeks"`, `"max"`等）またはカスタムオブジェクトでキャッシュ期間を指定できる。

**機能の利用シーン**：高頻度更新データ（秒単位のキャッシュ）、日次更新データ（日単位のキャッシュ）、ほぼ変更されないマスタデータ（max期間キャッシュ）など、データの更新頻度に応じたキャッシュ戦略の設定。

**主要な処理内容**：
1. `"use cache"`関数内での呼び出しバリデーション
2. プロファイル名の場合はnext.config.jsの設定から解決
3. カスタムオブジェクトの場合はバリデーション
4. WorkUnitStore（UseCacheStore）のexplicitRevalidate/explicitExpire/explicitStaleを更新

**関連システム・外部連携**：next.config.jsのcacheLife設定、WorkUnitStore

**権限による制御**：なし。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | - | - | 本機能は画面に直接関連しない |

## 機能種別

設定 / キャッシュ制御

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| profile | string \| CacheLife | Yes | プロファイル名またはカスタムキャッシュ設定 | プロファイル名はnext.config.jsに存在する必要あり |
| profile.stale | number | No | クライアントキャッシュ期間（秒） | 数値のみ（falseは不可、Infinityを使用） |
| profile.revalidate | number | No | サーバー再検証間隔（秒） | 数値のみ（falseは不可、Infinityを使用） |
| profile.expire | number | No | キャッシュ有効期限（秒） | 数値のみ。revalidateより大きい値 |

### 入力データソース

関数の引数から直接取得。プロファイル名の場合はWorkStoreのcacheLifeProfilesから設定値を取得。

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| （なし） | void | 戻り値なし。副作用としてUseCacheStoreを更新 |

### 出力先

WorkUnitStore（UseCacheStore）のexplicitRevalidate/explicitExpire/explicitStaleフィールドを更新。

## 処理フロー

### 処理シーケンス

```
1. cacheLife(profile) 呼び出し
2. __NEXT_USE_CACHE環境変数チェック
3. WorkUnitStoreの型チェック（'cache'または'private-cache'のみ許可）
4. profileが文字列の場合:
   a. WorkStoreからcacheLifeProfiles取得
   b. プロファイル名で設定を検索
   c. 見つからない場合はエラー
5. profileがオブジェクトの場合:
   a. validateCacheLife()でバリデーション
6. 各値をUseCacheStoreに設定（より小さい値が優先）
```

### フローチャート

```mermaid
flowchart TD
    A[cacheLife呼び出し] --> B{__NEXT_USE_CACHE?}
    B -->|No| C[エラースロー]
    B -->|Yes| D{use cache内?}
    D -->|No| E[エラースロー]
    D -->|Yes| F{profileの型}
    F -->|string| G[cacheLifeProfilesから解決]
    G --> H{プロファイル存在?}
    H -->|No| I[エラースロー]
    H -->|Yes| J[profile取得]
    F -->|object| K[validateCacheLife]
    J --> L[explicitRevalidate更新]
    K --> L
    L --> M[explicitExpire更新]
    M --> N[explicitStale更新]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-45-01 | use cache内限定 | cacheLife()は"use cache"関数内でのみ呼び出し可能 | 常時 |
| BR-45-02 | 最小値優先 | 同一キャッシュスコープ内で複数回呼ばれた場合、最小値が採用される | 複数呼び出し時 |
| BR-45-03 | expire >= revalidate | expire値はrevalidate値以上でなければならない | 両方指定時 |
| BR-45-04 | falseは不可 | stale/revalidate/expireにfalseは指定不可。Infinityを使用する | 常時 |

### 計算ロジック

- CacheLifeはHTTPのCache-Controlヘッダーに類似: `stale` = max-age, `revalidate` = s-maxage, `expire` = stale-while-revalidate + revalidate

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

本機能はデータベースを操作しない。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | Error | cacheComponents設定なし | エラーメッセージで設定方法を案内 |
| - | Error | "use cache"関数外での呼び出し | エラースロー |
| - | Error | 未定義のプロファイル名 | next.config.jsの設定例を表示 |
| - | Error | revalidate > expire | expire >= revalidateを要求 |
| - | Error | stale/revalidate/expireにfalseを指定 | Infinityの使用を案内 |
| - | InvariantError | cacheLifeProfilesが未提供 | InvariantError |

### リトライ仕様

不要。

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

不要。

## パフォーマンス要件

即座に完了する同期処理のため特に要件なし。

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

特になし。

## 備考

- デフォルトプロファイル名: `'default'`, `'seconds'`, `'minutes'`, `'hours'`, `'days'`, `'weeks'`, `'max'`
- TypeScriptの型はnext-types-pluginで上書きされ、カスタムプロファイル名も型チェック対象となる
- `cacheComponents`設定（experimental）が必要

---

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

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

### 推奨読解順序

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | cache-life.ts | `packages/next/src/server/use-cache/cache-life.ts` | CacheLife型（5-15行目）: stale, revalidate, expireの3プロパティ |

**読解のコツ**: 17行目のコメントがCache-Controlヘッダーとの対応を示している。

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

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | cache-life.ts | `packages/next/src/server/use-cache/cache-life.ts` | `cacheLife()`関数（77-174行目） |

**主要処理フロー**:
1. **78-82行目**: __NEXT_USE_CACHEチェック
2. **84-103行目**: WorkUnitStoreの型チェック（cache/private-cacheのみ許可）
3. **105-145行目**: プロファイル名解決またはオブジェクトバリデーション
4. **147-173行目**: explicitRevalidate/explicitExpire/explicitStaleの更新

#### Step 3: バリデーション処理を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | cache-life.ts | `packages/next/src/server/use-cache/cache-life.ts` | `validateCacheLife()`関数（34-75行目） |

#### Step 4: 収集された値の利用箇所を理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | use-cache-wrapper.ts | `packages/next/src/server/use-cache/use-cache-wrapper.ts` | `collectResult()`関数（384-507行目）: explicitRevalidate/explicitExpire/explicitStaleの参照（436-447行目） |

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

```
cacheLife(profile)
    │
    ├─ workUnitAsyncStorage.getStore()
    ├─ workAsyncStorage.getStore()
    │      └─ cacheLifeProfiles[profile]  (文字列の場合)
    ├─ validateCacheLife(profile)  (オブジェクトの場合)
    └─ workUnitStore.explicitRevalidate/explicitExpire/explicitStale 更新
```

### データフロー図

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

profile ───▶ cacheLife() ───▶ UseCacheStore更新
  │              │                    │
  ├─ string ──▶ cacheLifeProfiles    ├─ explicitRevalidate
  └─ object ──▶ validateCacheLife    ├─ explicitExpire
                                      └─ explicitStale
                                            │
                                      collectResult()で参照
                                            │
                                      CacheEntry生成
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| cache-life.ts | `packages/next/src/server/use-cache/cache-life.ts` | ソース | cacheLife()の実装 |
| use-cache-wrapper.ts | `packages/next/src/server/use-cache/use-cache-wrapper.ts` | ソース | collectResult()での値利用 |
| work-unit-async-storage.external.ts | `packages/next/src/server/app-render/work-unit-async-storage.external.ts` | ソース | UseCacheStore型定義 |
