active: true
derived: false
gherkin: |
  Feature: cached_run context manager
    Scenario: Temporarily caching functions within a block
      Given a Spot instance and one or more target functions
      When the functions are passed to the cached_run context manager
      Then temporary cached wrappers are yielded for use within the block
groups:
- CACHE
header: |
  cached_run コンテキストマネージャ
level: 2.2
links:
- ARCH001: njFV9W_NXjx3dMCDMAVXf0g99DYN8tKwPHU5nP1tFhA=
normative: true
ref: ''
reviewed: Z-CyQZ4Q5F-ZTxxZcCiFZVki6JczHjfMYhAbwVcw3k8=
text: |
  ## インターフェース

  ```python
  @contextmanager
  def cached_run(
      self,
      *funcs: Any,
      **kwargs: Any
  ) -> Iterator[Any]: ...
  ```

  ## 振る舞い

  ### 基本フロー

  1. `Spot` インスタンスからコンテキストマネージャとして呼び出される。
  2. 引数 `funcs` に渡された関数が0個の場合はエラーを送出する。
  3. 各関数に対して、`Spot.mark(**kwargs)` で生成したキャッシュデコレータを適用し、ラップされた関数を生成する。
  4. ラップされた関数を `yield` してコンテキストブロック内のユーザーコードに提供する。
  5. ユーザーコード内での実行は、通常の `@spot.mark` 適用済み関数と同様にキャッシュ機構を経由する。
  6. コンテキストブロック終了時のクリーンアップ処理は特に行わない（一時的なラッパーはスコープを抜けると破棄される）。

  ## パラメータ詳細

  | パラメータ | 必須 | 説明 |
  |---|---|---|
  | `*funcs` | はい | キャッシュ機能を適用したい対象の関数。外部ライブラリの関数なども指定可能。複数指定可能。 |
  | `**kwargs` | いいえ | `Spot.mark` デコレータに渡すオプション引数（`save_blob`, `keygen`, `version`, `content_type`, `serializer`, `retention`, `save_sync`, `hooks` 等）。 |

  ## 戻り値（Yields）の仕様

  - **1つの関数**を渡した場合: ラップされた単一の callable が返る。
  - **複数の関数**を渡した場合: ラップされた callable のタプルが返る。

  ## エラーハンドリング

  - **引数エラー**: `funcs` が空（0個）の場合、`beautyspot.exceptions.ValidationError` を送出し、コンテキストに入らない。

  ## エッジケース

  - 非同期関数やジェネレータ関数を渡した場合の挙動は、基底となる `mark` デコレータの制約に完全に依存する。
  - 適用されるキャッシュキーは元の関数に基づくため、同名・同シグネチャの別関数が混同されないように `KeyGen` のスコープ規則に従う。

  ## 設計判断

  デコレータを使えないケース（外部ライブラリの関数など）や、動的にキャッシュ適用を制御したいケースに対応するため。コンテキストマネージャとして提供することで、実行のスコープとリソースのライフサイクルを明確化する。
