active: true
derived: false
groups:
- SERIAL
header: |
  タスクごとのシリアライザの上書き
level: 1.18
links:
- ARCH005: f7IpeWL9LR7SQ3LP4FNILP4SUho1yMVkYhHP8_dKm8Y=
- REQ005: iMDbh51FT-Eu8XByvRDwGCzvXD7iYGh6c5AwH9v0RxA=
normative: true
ref: ''
reviewed: MdfaNr6xgwiXct00WQDVw-RTvQ760LhpIQgyVWpUkDE=
status: accepted
text: |
  # タスクごとのシリアライザの上書き

  ## コンテキストと課題

  プロジェクト全体としては安全性と互換性の観点から `msgpack` を標準シリアライザとしています。
  しかし、探索的データ分析（EDA）やプロトタイピング、あるいは `msgpack` でのシリアライズが困難なサードパーティ製オブジェクトを扱う特定のタスクにおいては、Python標準の `pickle` のような柔軟なシリアライザを局所的に使用したいというニーズがあります。

  ## 判断基準

  * **Flexibility**: 標準シリアライザで扱いにくい特殊なオブジェクトに対して、最適な保存方法を選択できること。
  * **Locality**: プロジェクト全体の設定（セキュリティポリシー等）を損なうことなく、特定の箇所だけで設定を上書きできること。
  * **Fault Tolerance**: オーバーライドされたシリアライザでエラーが発生しても、再計算によって実行を継続できること。

  ## 検討した選択肢

  * **Option 1**: グローバルなシリアライザ設定のみを提供し、個別の変更は認めない。
  * **Option 2**: `Spot.mark()` および `Spot.cached_run()` に `serializer` 引数を追加し、局所的なオーバーライドを可能にする。

  ## 決定事項

  採用した選択肢: **Option 2**.

  1.  **Override Mechanism:** `Spot.mark()` および `Spot.cached_run()` に、オプショナル引数 `serializer` を追加します。
  2.  **Protocol:** ユーザーは `dumps(obj) -> bytes` および `loads(bytes) -> obj` メソッドを持つ任意のオブジェクトを渡すことができます。
  3.  **Fallback Behavior:** 指定されたシリアライザでデシリアライズに失敗した場合、ADR-0003 の方針に従い、キャッシュ破損として扱い、タスクを再実行します。

  ## 影響・結果

  * **ポジティブ**:
      * ユーザーはプロジェクト全体の設定を変更することなく、必要な箇所だけで `pickle` 等の機能を利用できる。
      * キャッシュが読み込めなくなった場合も、自動的に再計算されるため、開発体験（DX）が損なわれない。
  * **ネガティブ**:
      * `pickle` を使用したタスクは、異なる環境間や長期間の保存において互換性が保証されない。
      * `Spot.register()` で登録したカスタム型変換は、オーバーライドされたシリアライザには適用されない。
