← 全体レポートに戻る

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

生成日時: 2026-03-13 23:59:51

対象アイテム

10

REQ

1

ARCH

1

SPEC

2

TST

2

IMPL

2

ADR

2

レビュー済

10/10

Suspect

0

グループ

LIFE
アイテム: REQ007 ARCH007 SPEC016 SPEC017 TST016 TST017 IMPL016 IMPL017 ADR032 ADR038

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

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

グループREQARCHSPECTSTIMPLADR
LIFEREQ007
キャッシュの有効期限を関数名パターンに基づくルールで設定できること。個別の関数に対して保持期間を指定でき、期限切れのキャッシュを自動的に無効化できること。
ARCH007
## コンポーネント構成 ```mermaid graph TD A[core.Spot] -->|マッチング要求| B[LifecyclePolicy]...
SPEC016
## インターフェース ```python class LifecyclePolicy: def add_rule(self, pattern: st...
TST016
## 目的 `LifecyclePolicy` はキャッシュデータの保持期間を関数名パターンで制御する。パターンマッチングの不備は、重要なキャッシュの意図しな...
IMPL016
## 実装概要 `LifecyclePolicy` クラスは `Rule` オブジェクトのリストを保持し、 関数名に基づいてキャッシュの保持期間を決定する。 ...
ADR032
# Declarative Lifecycle Policy ## Context and Problem Statement / コンテキスト 機械学習や...
LIFEREQ007
キャッシュの有効期限を関数名パターンに基づくルールで設定できること。個別の関数に対して保持期間を指定でき、期限切れのキャッシュを自動的に無効化できること。
ARCH007
## コンポーネント構成 ```mermaid graph TD A[core.Spot] -->|マッチング要求| B[LifecyclePolicy]...
SPEC017
## インターフェース ```python def parse_retention(val: Any) -> float | None: ... ``` #...
TST017
## 目的 `Retention` はキャッシュの有効期間をユーザーフレンドリーな形式で指定する値オブジェクトである。パースの不備は意図しない保持期間(例: ...
IMPL017
## 実装概要 `Retention` クラスを名前空間として使用し、保持期間のパースや 特殊な定数(`INDEFINITE`, `FOREVER`)を管理す...
ADR032
# Declarative Lifecycle Policy ## Context and Problem Statement / コンテキスト 機械学習や...
LIFEREQ007
キャッシュの有効期限を関数名パターンに基づくルールで設定できること。個別の関数に対して保持期間を指定でき、期限切れのキャッシュを自動的に無効化できること。
ARCH007
## コンポーネント構成 ```mermaid graph TD A[core.Spot] -->|マッチング要求| B[LifecyclePolicy]...
SPEC016
## インターフェース ```python class LifecyclePolicy: def add_rule(self, pattern: st...
TST016
## 目的 `LifecyclePolicy` はキャッシュデータの保持期間を関数名パターンで制御する。パターンマッチングの不備は、重要なキャッシュの意図しな...
IMPL016
## 実装概要 `LifecyclePolicy` クラスは `Rule` オブジェクトのリストを保持し、 関数名に基づいてキャッシュの保持期間を決定する。 ...
ADR038
# Probabilistic Auto-Eviction for Storage Maintenance ## Context and Problem St...
LIFEREQ007
キャッシュの有効期限を関数名パターンに基づくルールで設定できること。個別の関数に対して保持期間を指定でき、期限切れのキャッシュを自動的に無効化できること。
ARCH007
## コンポーネント構成 ```mermaid graph TD A[core.Spot] -->|マッチング要求| B[LifecyclePolicy]...
SPEC017
## インターフェース ```python def parse_retention(val: Any) -> float | None: ... ``` #...
TST017
## 目的 `Retention` はキャッシュの有効期間をユーザーフレンドリーな形式で指定する値オブジェクトである。パースの不備は意図しない保持期間(例: ...
IMPL017
## 実装概要 `Retention` クラスを名前空間として使用し、保持期間のパースや 特殊な定数(`INDEFINITE`, `FOREVER`)を管理す...
ADR038
# Probabilistic Auto-Eviction for Storage Maintenance ## Context and Problem St...

カバレッジ(局所)

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

アイテム詳細

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

キャッシュの有効期限を関数名パターンに基づくルールで設定できること。個別の関数に対して保持期間を指定でき、期限切れのキャッシュを自動的に無効化できること。

親:

子: ADR032, ADR038, ARCH007

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

コンポーネント構成

graph TD
  A[core.Spot] -->|マッチング要求| B[LifecyclePolicy]
  B -->|ルールリスト| C[Rule]
  C -->|パターン照合| D[fnmatch]
  B -->|パース| E[Retention]

コンポーネント責務

コンポーネント 責務 インターフェース
LifecyclePolicy 複数のルールを管理し、関数名に最適な有効期限を決定する resolve_with_fallback()
Rule 1つのパターンとそれに対応する保持期間のペア match(func_name)
Retention 多様な時間表現(文字列/数値)を秒数に正規化する parse_retention()

データフロー

sequenceDiagram
  participant Spot as core.Spot
  participant Policy as LifecyclePolicy
  participant DB as TaskDB

  Spot->>Policy: resolve_with_fallback("module.func")
  Policy->>Policy: ルール順次照合 (fnmatch)
  Policy-->>Spot: expires_at (timestamp)
  Spot->>DB: save(..., expires_at)
  Note over DB: get() 時に現在時刻と比較判定

技術選定

技術領域 選定 理由
パターンマッチ fnmatch (Glob) 正規表現よりも直感的で、開発者にとって馴染みのある指定方法
保持期間指定 文字列パーサー ("30d"等) 設定ファイルやデコレータでの可読性を向上
判定タイミング 遅延判定 (Lazy) 書き込み・読み込み時のオーバーヘッドを最小化

非機能要件方針

親: REQ007

子: SPEC016, SPEC017

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

インターフェース

class LifecyclePolicy:
    def add_rule(self, pattern: str, retention: Any) -> None: ...
    def resolve_with_fallback(self, func_name: str) -> float | None: ...

振る舞い

  1. 順次照合: 登録された順にルールを走査する

  2. パターンマッチ: fnmatch.fnmatch を使用し、関数名がパターンに合致するか判定

  3. 二段階解決:

    1. 最初に「完全修飾名 (module.qualname)」で照合

    2. マッチしなければ「短縮名 (qualname)」で照合

  4. 結果返却: 最初にマッチしたルールの保持期間を秒数に変換して返す

パラメータ詳細

パラメータ例説明pattern"my_mod.*", "*_test"Glob形式のパターンretention"30d", 3600保持期間の定義

デフォルト保持期間

エラーハンドリング

エッジケース

親: ARCH007

子: IMPL016, TST016

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

インターフェース

def parse_retention(val: Any) -> float | None: ...

振る舞い

文字列パース

数値・オブジェクト

パラメータ詳細 (単位)

単位 倍率 (秒) 備考
d 86400 日数
h 3600 時間
m 60
s 1

エラーハンドリング

エッジケース

親: ARCH007

子: IMPL017, TST017

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

目的

LifecyclePolicy はキャッシュデータの保持期間を関数名パターンで制御する。パターンマッチングの不備は、重要なキャッシュの意図しない削除(データロス)や不要なキャッシュの蓄積(ディスク圧迫)を引き起こす。

検証観点

references: tests/unit/test_lifecycle.py

親: SPEC016

子:

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

目的

Retention はキャッシュの有効期間をユーザーフレンドリーな形式で指定する値オブジェクトである。パースの不備は意図しない保持期間(例: "7d" を 7秒と誤解釈)を招き、重要なキャッシュの早期削除やディスクの際限ない肥大化に繋がる。

検証観点

references: tests/unit/test_lifecycle_extended.py

親: SPEC017

子:

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

実装概要

LifecyclePolicy クラスは Rule オブジェクトのリストを保持し、 関数名に基づいてキャッシュの保持期間を決定する。 resolve() メソッドが fnmatch.fnmatch() を使って関数名をパターンと照合し、 最初にマッチしたルールの保持期間を返す。

設計判断

First-Match セマンティクス

ルールのリストは順序が意味を持ち、最初にマッチしたものが採用される。 これにより、特定プレフィックスの関数には短い保持期間を設定し、 最後に *(ワイルドカード)でデフォルトポリシーを設定するような フォールバック構造が簡単に記述できる。

resolve_with_fallback の導入

後方互換性と柔軟性のため、まず func_identifier (モジュール名付きの完全修飾名) で マッチングを試み、マッチしなかった場合は func_name (短い関数名) で再度マッチングを 試みる resolve_with_fallback() を提供している。

default_retention の導入

LifecyclePolicy コンストラクタに default_retention パラメータを追加。 どのルールにもマッチしない場合に返す保持期間を指定できる。 LifecyclePolicy.default()default_retention="30d" で生成し、 デフォルトで30日の保持期間を設定する。

実装メモ

references: src/beautyspot/lifecycle.py

親: SPEC016

子:

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

実装概要

Retention クラスを名前空間として使用し、保持期間のパースや 特殊な定数(INDEFINITE, FOREVER)を管理する。 parse_retention() 関数は文字列("7d", "12h"等)、timedelta、 または秒数(int/float)を受け取り、標準化された timedelta オブジェクトに変換する。

設計判断

_ForeverSentinel シングルトン

Retention.FOREVER はポリシーを強制的にバイパスするための特殊値。 PEP 703 (free-threading) 環境での安全性を考慮し、 _ForeverSentinelthreading.Lock を用いたダブルチェックロッキングで 厳密なシングルトンとして実装されている。

直感的な文字列表現のサポート

"7d", "12h", "30m", "10s" のような文字列フォーマットを 正規表現 _TIME_PATTERN でパースすることで、設定ファイルや ハードコード時の可読性を高めている。

実装メモ

references: src/beautyspot/lifecycle.py

親: SPEC017

子:

ADR032 ADR {h(g)} ✓ レビュー済

Declarative Lifecycle Policy

Context and Problem Statement / コンテキスト

機械学習や生成AIの実験プロセスにおいて、生成されるデータの重要度は均一ではありません。数ヶ月保持すべき「最終モデル」もあれば、数時間で不要になる「一時的なデバッグ出力」もあります。

現在、これらの古いデータを削除するには、ユーザーが MaintenanceService.prune(older_than=...) を呼び出すスクリプトを自作し、定期実行する必要があります。これはユーザーにとって負担であり、設定を忘れるとディスク容量を圧迫する原因となります。また、beautyspot は常駐プロセスを持たないため、クリーンアップのトリガー設計が課題となります。

Decision Drivers / 要求

Considered Options / 検討

Decision Outcome / 決定

Chosen option: Option 2.

ユーザーが「データの寿命(What)」を宣言するだけで済むよう、以下の仕組みを導入します。

1. retention Parameter for @mark

デコレータおよび run メソッドに retention 引数を追加します(例: "7d", "1h", None)。

2. Database Schema Change (expires_at)

タスク作成時に寿命を計算し、tasks テーブルの expires_at カラムに保存します。

3. Lazy Expiration (Access-time Check)

キャッシュ取得時(spot.db.get)に、expires_at < current_time であれば「キャッシュミス」とみなして None を返します。この時点では物理削除は行わず、レイテンシへの影響を最小限にします。

4. Explicit Garbage Collection (CLI)

期限切れデータの物理削除は、CLI コマンド $ beautyspot gc --expired によって一括で行います。

Consequences / 決定

親: REQ007

子:

ADR038 ADR {h(g)} ✓ レビュー済

Probabilistic Auto-Eviction for Storage Maintenance

Context and Problem Statement / コンテキスト

beautyspot はキャッシュの TTL をサポートしており、期限切れデータは論理的に無効化されます。しかし、ユーザーが明示的にクリーンアップを呼び出さない限り、有効期限切れのメタデータや巨大な孤立 Blob ファイルは物理的に削除されず、ストレージが肥大化し続けるという問題がありました。

ユーザーにインフラ管理を意識させない「黒子」としての哲学を維持しつつ、自動でガベージコレクション(エビクション)を行う仕組みが必要になりました。

Decision Drivers / 要求

Considered Options / 検討

  1. Capacity-based LRU (Least Recently Used) Policy:
    • ストレージ容量やレコード数の上限に達した際に古いデータを削除する。
    • 評価: 却下。キャッシュヒットのたびにタイムスタンプを更新する必要があり、DB の書き込み競合やレイテンシ低下を招く。
  2. Load-Adaptive Background Eviction:
    • アイドル状態のときにのみクリーンアップタスクを投入する。
    • 評価: 却下。実装が複雑になりすぎる(オーバーエンジニアリング)。
  3. Probabilistic Auto-Eviction (確率的自動実行):
    • 新しい結果の保存直後、設定された確率に基づいてバックグラウンドでクリーンアップタスクを投入する。
    • 評価: 採用。 シンプルかつ低コスト。

Decision Outcome / 決定

Chosen option: Option 3.

確率的自動エビクションを採用します。

Consequences / 決定

親: REQ007

子: