← 全体レポートに戻る

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

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

対象アイテム

8

REQ

1

ARCH

1

SPEC

2

TST

2

IMPL

2

レビュー済

8/8

Suspect

0

グループ

DB
アイテム: REQ003 ARCH003 SPEC007 SPEC008 TST007 TST008 IMPL007 IMPL008

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

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

グループREQARCHSPECTSTIMPL
DBREQ003
キャッシュのメタデータ(関数名、入力ID、バージョン、有効期限等)をデータベースに永続化できること。 抽象インターフェースにより、DBやストレージなどのバック...
ARCH003
## コンポーネント構成 ```mermaid classDiagram class TaskDBCore { <<Protocol>> ...
SPEC007
## インターフェース ```python class SQLiteTaskDB(TaskDBBase): def __init__(self, db...
TST007
## 目的 `SQLiteTaskDB` はキャッシュメタデータの永続化を担う中核コンポーネントであり、DB の不整合はキャッシュの消失や重複実行を引き起こす...
IMPL007
## 実装概要 `SQLiteTaskDB` クラスが中核。Writer Thread + Reader Threads パターンで実装。 単一の `_wri...
DBREQ003
キャッシュのメタデータ(関数名、入力ID、バージョン、有効期限等)をデータベースに永続化できること。 抽象インターフェースにより、DBやストレージなどのバック...
ARCH003
## コンポーネント構成 ```mermaid classDiagram class TaskDBCore { <<Protocol>> ...
SPEC008
## インターフェース ```python @runtime_checkable class TaskDBCore(Protocol): def ge...
TST008
## 目的 `TaskDBCore` / `TaskDBBase` のプロトコル階層は、サードパーティによるカスタムDB実装(Redis、PostgreSQL...
IMPL008
## 実装概要 DB 層のプロトコル階層を定義。`TaskDBCore`(ランタイム必須の CRUD)、 `Flushable`(書き込み同期)、`Shutd...

カバレッジ(局所)

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

アイテム詳細

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

キャッシュのメタデータ(関数名、入力ID、バージョン、有効期限等)をデータベースに永続化できること。

抽象インターフェースにより、DBやストレージなどのバックエンド実装を差し替え可能であること。

親:

子: ARCH003

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

コンポーネント構成

classDiagram
  class TaskDBCore {
    <<Protocol>>
    +init_schema() void
    +get(cache_key) TaskRecord
    +save(cache_key, ...) void
    +delete(cache_key) bool
  }
  class Maintenable {
    <<Protocol>>
    +delete_expired() int
    +prune(older_than) int
    +delete_all() int
  }
  class TaskDBMaintenable {
    <<Protocol>>
  }
  TaskDBCore <|-- TaskDBMaintenable
  Maintenable <|-- TaskDBMaintenable

  class SQLiteTaskDB {
    -db_path: Path
    -_write_queue: Queue
    +init_schema() void
    +get(cache_key) TaskRecord
    +save(cache_key, ...) void
  }
  TaskDBMaintenable <|-- SQLiteTaskDB

コンポーネント責務

コンポーネント 責務 インターフェース
TaskDBCore キャッシュ実行時に必要な最小限のメタデータDBアクセス init_schema(), get(), save(), delete()
Maintenable GCやCLI等、運用・保守に必要な拡張操作 delete_expired(), prune(), delete_all()
TaskDBMaintenable 実行用と保守用の両方を備えた上位Protocol TaskDBCore + Maintenable
SQLiteTaskDB SQLiteを用いたデフォルト実装。非同期書き込みキューを内包 TaskDBMaintenable 実装

データフロー

sequenceDiagram
  participant Spot as core.Spot
  participant DB as SQLiteTaskDB
  participant Q as WriteQueue
  participant Thread as WriterThread
  participant SQLite as SQLiteDB

  Spot->>DB: get(cache_key)
  DB->>SQLite: SELECT
  SQLite-->>DB: TaskRecord
  DB-->>Spot: TaskRecord

  Spot->>DB: save(metadata)
  DB->>Q: put(WriteTask)
  DB-->>Spot: void (Non-blocking)

  Thread->>Q: get()
  Thread->>SQLite: INSERT / UPDATE

技術選定

技術領域 選定 理由
デフォルトメタデータDB SQLite ゼロ設定、組み込み可能、ローカルキャッシュとして十分な性能
バックグラウンド書き込み キュー + 専用スレッド SQLiteの排他制御によるメインスレッドのブロックを防ぐため
抽象化 ProtocolベースのDI TaskDBCoreを満たせばPostgreSQL等に容易に差し替え可能

非機能要件方針

親: REQ003

子: SPEC007, SPEC008

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

インターフェース

class SQLiteTaskDB(TaskDBBase):
    def __init__(self, db_path: str | Path, timeout: float = 30.0): ...
    def save(self, task: TaskRecord) -> None: ...
    def get(self, cache_key: str, *, include_expired: bool = False) -> TaskRecord | None: ...

振る舞い

ライタースレッド方式

読み取り並行性

スキーマ管理

パラメータ詳細

設定 デフォルト 説明
journal_mode WAL 書き込みと読み取りの並行性を高める設定
synchronous NORMAL パフォーマンスと耐久性のバランス設定
timeout 30.0 データベースロック待機時間の閾値

エラーハンドリング

エッジケース

親: ARCH003

子: IMPL007, TST007

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

インターフェース

@runtime_checkable
class TaskDBCore(Protocol):
    def get(self, cache_key: str, *, include_expired: bool = False) -> TaskRecord | None: ...
    def save(self, record: TaskRecord) -> None: ...

class TaskDBBase(ABC):
    # TaskDBCore を満たしつつ、メンテナンスのデフォルト実装を提供

振る舞い

階層構造

  1. TaskDBCore: キャッシュの実行に必要な最小限のメソッド定義
  2. Maintenable: GCや統計取得に必要な管理用メソッドの定義
  3. TaskDBBase: 共通のバリデーションや例外処理を実装する基底クラス

パラメータ詳細 (主要メソッド)

メソッド 役割
get_blob_refs() 全レコードの blob_key を列挙する(GC用)
delete_expired() expires_at を経過したレコードを一括削除する
get_history() 実行履歴(統計)を取得する

エラーハンドリング

エッジケース

親: ARCH003

子: IMPL008, TST008

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

目的

SQLiteTaskDB はキャッシュメタデータの永続化を担う中核コンポーネントであり、DB の不整合はキャッシュの消失や重複実行を引き起こす。WALモード・専用ライタースレッドという独自アーキテクチャの信頼性を保証する。

検証観点

references: tests/unit/test_db_robustness.py

親: SPEC007

子:

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

目的

TaskDBCore / TaskDBBase のプロトコル階層は、サードパーティによるカスタムDB実装(Redis、PostgreSQL 等)の差し替えを可能にする拡張ポイントである。インターフェース契約が不明確だと、カスタム実装が実行時に予期しないエラーを起こす。

検証観点

references: tests/unit/test_db_writer_queue.py

親: SPEC008

子:

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

実装概要

SQLiteTaskDB クラスが中核。Writer Thread + Reader Threads パターンで実装。 単一の _writer_thread(デーモン)が _write_queue から書き込みタスクを取り出して 直列処理し、読み取りは threading.local() のスレッドローカル接続で並行実行する。 WAL モードにより読み取りと書き込みが並行可能。

設計判断

専用ライタースレッドの採用

SQLite は単一書き込み接続しかサポートしないため、全書き込みを1つのスレッドに 集約する Producer-Consumer パターンを採用。キュー経由でタスクを受け渡し、 ライタースレッドがコミット/ロールバックを管理する。 マルチスレッドからの並行書き込みによるロック競合を根本的に回避する。

スレッドローカル読み取り接続

threading.local()_ReadConnWrapper を格納し、スレッドごとに 読み取り専用接続(PRAGMA query_only = ON)を保持する。 接続エラー時は自動的に再作成し、リーク防止のため WeakSet で全接続を追跡する。

_WriteTask 状態マシン

書き込みタスクを PENDING → RUNNING → DONE(または CANCELLED)の 状態マシンで管理。タイムアウト時の try_cancel() により、 キュー内で待機中のタスクを安全にキャンセルできる。 既に RUNNING 状態のタスクはキャンセルせず完了を待つ。

実装メモ

references: src/beautyspot/db.py

親: SPEC007

子:

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

実装概要

DB 層のプロトコル階層を定義。TaskDBCore(ランタイム必須の CRUD)、 Flushable(書き込み同期)、Shutdownable(安全な停止)、 Maintenable(GC・統計等の管理操作)の4つのプロトコルと、 それらを統合した TaskDBMaintenable を提供する。 TaskDBBase は ABC として Maintenable のデフォルト実装(安全な no-op)を提供する。

設計判断

プロトコルの細分化

単一の巨大インターフェースではなく、責務ごとにプロトコルを分割した。 これにより、カスタム DB 実装は TaskDBCore のみ実装すればランタイムで動作し、 メンテナンス機能は段階的にオプトインできる。

デフォルト実装の安全性

TaskDBBase のメンテナンスメソッド(delete_expired(), prune() 等)は デフォルトで空リスト返却や no-op を行い、サブクラスが未実装でも安全に動作する。 CLI の gc コマンドが未対応の DB バックエンドでもエラーにならない設計。

実装メモ

references: src/beautyspot/db.py

親: SPEC008

子: