← 全体レポートに戻る

局所トレーサビリティビュー グループ: KEY

生成日時: 2026-03-11 00:06:09

対象アイテム

11

REQ

1

ARCH

1

SPEC

3

TST

3

IMPL

3

レビュー済

11/11

Suspect

0

グループ

KEY
アイテム: REQ002 ARCH002 SPEC004 SPEC005 SPEC006 TST004 TST005 TST006 IMPL004 IMPL005 IMPL006

トレーサビリティマトリクス

✓=レビュー済 ○=未レビュー ⚠=Suspect(複数同時表示あり。IDクリックで詳細へ)

グループREQARCHSPECTSTIMPL
KEYREQ002
関数の引数から安定かつ一意なキャッシュキーを生成できること。引数の型・構造に応じた正規化を行い、辞書のキー順序やコレクション型の違いを正しく区別できること。
ARCH002
## コンポーネント構成 ```mermaid graph TD A[core.Spot] -->|キャッシュキー生成要求| B[KeyGenPolicy...
SPEC004
## インターフェース ```python class KeyGen: @staticmethod def _default(args: tu...
TST004
## 目的 キャッシュキーはキャッシュの同一性判定の基盤であり、ハッシュが不安定だとキャッシュミスの頻発(性能劣化)や誤ヒット(データ不整合)を引き起こす。P...
IMPL004
## 実装概要 `KeyGen` クラスの静的メソッド群がキャッシュキー生成を担う。 `_default(args, kwargs)` が主要なエントリポイン...
KEYREQ002
関数の引数から安定かつ一意なキャッシュキーを生成できること。引数の型・構造に応じた正規化を行い、辞書のキー順序やコレクション型の違いを正しく区別できること。
ARCH002
## コンポーネント構成 ```mermaid graph TD A[core.Spot] -->|キャッシュキー生成要求| B[KeyGenPolicy...
SPEC005
## インターフェース ```python @singledispatch def canonicalize(obj: Any) -> Any: ... ``...
TST005
## 目的 `canonicalize()` は引数の型ごとに正規化ルールを適用し、論理的に同値な入力が同じキャッシュキーを生成することを保証する。正規化の不...
IMPL005
## 実装概要 `canonicalize()` は `functools.singledispatch` で実装された再帰的正規化関数。 型ごとにディスパッ...
KEYREQ002
関数の引数から安定かつ一意なキャッシュキーを生成できること。引数の型・構造に応じた正規化を行い、辞書のキー順序やコレクション型の違いを正しく区別できること。
ARCH002
## コンポーネント構成 ```mermaid graph TD A[core.Spot] -->|キャッシュキー生成要求| B[KeyGenPolicy...
SPEC006
## インターフェース ```python class Strategy(Enum): DEFAULT = auto() # 再帰的正規化 ...
TST006
## 目的 `KeyGenPolicy` は引数ごとのキー生成戦略をカスタマイズする機構であり、ログレベルやデバッグフラグのような非決定的引数をキーから除外し...
IMPL006
## 実装概要 `Strategy` enum(DEFAULT, IGNORE, FILE_CONTENT, PATH_STAT の4種)と `KeyGenP...

カバレッジ(局所)

リンク方向カバー数カバー率未カバー
ARCH → REQ 1 / 1 100.0%
SPEC → ARCH 1 / 1 100.0%
TST → SPEC 3 / 3 100.0%
IMPL → SPEC 3 / 3 100.0%

アイテム詳細

REQ002 REQ {h(g)} ✓ レビュー済

関数の引数から安定かつ一意なキャッシュキーを生成できること。引数の型・構造に応じた正規化を行い、辞書のキー順序やコレクション型の違いを正しく区別できること。

親:

子: ARCH002

ARCH002 ARCH {h(g)} ✓ レビュー済

コンポーネント構成

graph TD
  A[core.Spot] -->|キャッシュキー生成要求| B[KeyGenPolicy]
  B -->|バインド| C[bound_keygen]
  C -->|引数別戦略| D[Strategy]
  C -->|正規化| E[canonicalize]
  C -->|ハッシュ計算| F[KeyGen.hash_items]
  E --> F

コンポーネント責務

コンポーネント 責務 インターフェース
KeyGenPolicy 関数の引数に対するハッシュ化戦略(無視、ファイル内容等)の宣言的定義と保持。 bind(func)
Strategy 引数ごとの処理方法(DEFAULT, IGNORE, FILE_CONTENT, PATH_STAT)の定義。 -
canonicalize Pythonオブジェクトを再帰的に正規化し、Msgpackで安定してシリアライズ可能な状態に変換。 @singledispatch canonicalize(obj)
KeyGen 正規化されたリストからSHA-256ハッシュを生成。レガシーデフォルトのハッシュ生成も担う。 hash_items(items), from_file_content(path)

データフロー

sequenceDiagram
  participant Spot as core.Spot
  participant KP as KeyGenPolicy
  participant Sig as inspect.signature
  participant Can as canonicalize
  participant KG as KeyGen

  Spot->>KP: bind(func)
  KP->>Sig: signature(func)
  Sig-->>KP: bound_keygen 生成
  KP-->>Spot: bound_keygen
  Spot->>Spot: bound_keygen(*args, **kwargs)
  loop 各引数
    alt Strategy.IGNORE
      Spot->>Spot: スキップ
    else Strategy.FILE_CONTENT
      Spot->>KG: from_file_content(path)
    else Strategy.PATH_STAT
      Spot->>KG: from_path_stat(path)
    else Strategy.DEFAULT
      Spot->>Can: canonicalize(val)
      Can-->>Spot: 正規化済みデータ
    end
  end
  Spot->>KG: hash_items(items_to_hash)
  KG-->>Spot: SHA-256 ハッシュ文字列 (キャッシュキー)

技術選定

技術領域 選定 理由
引数のバインド inspect.signature argsとkwargsを定義順に正確にマッピングし、デフォルト値も適用するため
正規化 functools.singledispatch 型ごとの正規化ロジックを拡張可能かつクリーンに実装するため
シリアライズ msgpack 高速でバイナリセーフであり、一貫したバイト列表現を得るため
ハッシュ関数 SHA-256 衝突確率が極めて低く、暗号学的に安全かつ広くサポートされているため

非機能要件方針

親: REQ002

子: SPEC004, SPEC005, SPEC006

SPEC004 SPEC {h(g)} ✓ レビュー済

インターフェース

class KeyGen:
    @staticmethod
    def _default(args: tuple, kwargs: dict) -> str: ...

    @staticmethod
    def hash_items(items: list) -> str: ...

振る舞い

基本フロー (_default)

  1. 正規化: argskwargscanonicalize() により再帰的に正規化する
  2. パック: 正規化された構造 [args, kwargs] を MessagePack でバイナリにシリアライズする
  3. ハッシュ: バイナリデータに対して SHA-256 ハッシュを計算し、16進数文字列を返す

リストハッシュ (hash_items)

パラメータ詳細

パラメータ 説明
args tuple 関数の位置引数
kwargs dict 関数のキーワード引数
items list バインド済み引数の正規化値リスト

エラーハンドリング

エッジケース

親: ARCH002

子: IMPL004, TST004

SPEC005 SPEC {h(g)} ✓ レビュー済

インターフェース

@singledispatch
def canonicalize(obj: Any) -> Any: ...

振る舞い

singledispatch を使用し、型に応じた最適な正規化形式へ再帰的に変換する。

主要な型別の処理

パラメータ詳細

オブジェクト型 正規化後の形式 備考
numpy.ndarray ("__numpy__", shape, dtype, bytes) 高速かつ正確なハッシュを保証
OrderedDict ("__ordered_dict__", items) 挿入順序を保持したまま正規化
Pydantic Model ("__pydantic_v2__", schema) スキーマ情報をベースに判定

エラーハンドリング

エッジケース

親: ARCH002

子: IMPL005, TST005

SPEC006 SPEC {h(g)} ✓ レビュー済

インターフェース

class Strategy(Enum):
    DEFAULT = auto()      # 再帰的正規化
    IGNORE = auto()       # キー計算から除外
    FILE_CONTENT = auto() # ファイルの内容をハッシュ
    PATH_STAT = auto()    # パス+サイズ+更新時刻をハッシュ

class KeyGenPolicy:
    def bind(self, func: Callable) -> Callable[..., str]: ...

振る舞い

  1. バインド: bind(func) 時に inspect.signature を解析し、引数名とデフォルト値を把握する
  2. 適用: 呼び出し時に引数を実値にバインドし、デフォルト値を補填する
  3. 戦略実行: 引数名ごとに指定された Strategy を適用し、正規化された値のリストを作成する
  4. 集約: 全ての値を KeyGen.hash_items() で一つのハッシュにまとめる

パラメータ詳細

戦略 内容 用途
IGNORE キャッシュキーに含めない verboselogger 等、結果に影響しない引数
FILE_CONTENT ファイルを全読込してハッシュ化 入力ファイルの厳密な変更検知
PATH_STAT os.stat 情報を使用 大容量ファイルの高速な変更検知

エラーハンドリング

エッジケース

親: ARCH002

子: IMPL006, TST006

TST004 TST {h(g)} ✓ レビュー済

目的

キャッシュキーはキャッシュの同一性判定の基盤であり、ハッシュが不安定だとキャッシュミスの頻発(性能劣化)や誤ヒット(データ不整合)を引き起こす。Python バージョンやプラットフォームに依存しないキー生成の安定性を保証する。

検証観点

references: tests/unit/test_cachekey.py

親: SPEC004

子:

TST005 TST {h(g)} ✓ レビュー済

目的

canonicalize() は引数の型ごとに正規化ルールを適用し、論理的に同値な入力が同じキャッシュキーを生成することを保証する。正規化の不備は「同じ入力なのにキャッシュミス」または「異なる入力なのに誤ヒット」という致命的なバグに直結する。

検証観点

references: tests/unit/test_cachekey.py

親: SPEC005

子:

TST006 TST {h(g)} ✓ レビュー済

目的

KeyGenPolicy は引数ごとのキー生成戦略をカスタマイズする機構であり、ログレベルやデバッグフラグのような非決定的引数をキーから除外したり、ファイルパスの代わりにファイル内容でキーを生成するユースケースを支える。戦略の誤適用はキャッシュの正確性を根本から損なう。

検証観点

references: tests/unit/test_cachekey.py

親: SPEC006

子:

IMPL004 IMPL {h(g)} ✓ レビュー済

実装概要

KeyGen クラスの静的メソッド群がキャッシュキー生成を担う。 _default(args, kwargs) が主要なエントリポイントで、引数を canonicalize() で正規化 → msgpack でシリアライズ → SHA-256 でハッシュする。 最終キーは func_identifier:input_id[:version] 形式の文字列を SHA-256 した値。

設計判断

SHA-256 の採用

MD5 より衝突耐性が高く、Python 標準ライブラリの hashlib で利用可能。 キャッシュキーとして64文字の hex 文字列は十分にコンパクトで、 DB のインデックスとしても効率的。

msgpack 経由のシリアライズ

正規化結果を直接 str() でハッシュする方式と比較し、 msgpack はバイナリ表現が安定しており、Python バージョン間での repr() の差異に影響されない。

ファイルベースの戦略

from_file_content() はファイルを 65KB チャンクで読み取り、 拡張子をハッシュに含める。大きなファイルでもメモリ効率が良い。 from_path_stat() は mtime + size のみでハッシュし、 ファイル内容の読み取りを避ける高速版。ファイル不在時は "MISSING_{filepath}" を返し、不在自体をキーに反映する。

実装メモ

references: src/beautyspot/cachekey.py

親: SPEC004

子:

IMPL005 IMPL {h(g)} ✓ レビュー済

実装概要

canonicalize()functools.singledispatch で実装された再帰的正規化関数。 型ごとにディスパッチハンドラを登録し、ネストされたデータ構造を再帰的に正規化する。 各ハンドラは型タグ付きのタプルを返し、異なるコレクション型が同じ内容でも 区別されるようにする。

設計判断

singledispatch の採用

if/elif チェーンと比較して、新しい型のサポート追加が局所的で、 既存コードへの影響がない。numpy や Pydantic のようなオプショナル依存の 型ハンドラも、条件付きで登録できる。

型タグによるコレクション区別

[1, 2](list)と (1, 2)(tuple)を区別するため、 正規化結果に ("__list__", ...), ("__tuple__", ...) のように 型タグを含める。これにより、構造的に同一でも型が異なるデータが 異なるキャッシュキーを生成する。

bool vs int の区別

Python では True == 1 かつ isinstance(True, int) だが、 キャッシュキーとしては区別が必要。singledispatch は MRO 順でマッチするため、 boolint より先にチェックするインライン処理を base handler に配置した。

実装メモ

references: src/beautyspot/cachekey.py

親: SPEC005

子:

IMPL006 IMPL {h(g)} ✓ レビュー済

実装概要

Strategy enum(DEFAULT, IGNORE, FILE_CONTENT, PATH_STAT の4種)と KeyGenPolicy クラスで構成。KeyGenPolicy は引数名→戦略のマッピングを保持し、 bind(func)inspect.signature() を使って関数シグネチャにバインドされた キー生成関数を返す。ファクトリメソッド KeyGen.ignore(), KeyGen.map(), KeyGen.file_content(), KeyGen.path_stat() で宣言的にポリシーを構築できる。

設計判断

bind() によるシグネチャバインディング

デコレーション時に inspect.signature(func) を呼び、 位置引数・キーワード引数・デフォルト値を解決する。 これにより、呼び出し時にはシグネチャ解析のオーバーヘッドがなくなる。

Strategy enum による宣言的指定

引数ごとの戦略を enum で宣言する方式を採用。 関数を渡す方式(keygen=lambda ...)と比較して、 シリアライズ可能で、デバッグ時の可読性が高い。

実装メモ

references: src/beautyspot/cachekey.py

親: SPEC006

子: