active: true
derived: false
groups:
- DB
header: |
  SQLiteTaskDB
level: 2.7
links:
- ARCH003: hztRUPwAahIBkVhPgOSP_qIfRnh6FSkrUlxLmmzOQg8=
normative: true
ref: ''
reviewed: sJMHQsYaheuLAovC4gF8A1B8uCMnle_VZXvspVZkWwg=
text: |
  ## インターフェース

  ```python
  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: ...
  ```

  ## 振る舞い

  ### ライタースレッド方式
  - 書き込み操作は全て `_WriteTask` キューに投入され、専用のバックグラウンドスレッドで直列に実行される。これにより SQLite の `database is locked` エラーを回避する。

  ### 読み取り並行性
  - 読み取りはスレッドローカルな接続を使用し、`PRAGMA query_only = ON` 状態で並行して実行される。

  ### スキーマ管理
  - 起動時に `tasks` テーブルの存在を確認し、必要に応じて自動的に `ALTER TABLE` によるカラム追加（マイグレーション）を行う。

  ### タイムアウトとフェイルファスト
  - 全ての書き込み操作は `timeout` 秒以内に完了する必要がある。
  - **PENDING（未着手）状態**: `timeout` を超えた場合、タスクはキューから破棄（キャンセル）され、呼び出し元に `TimeoutError` を返す。
  - **RUNNING（実行中）状態**: `timeout` を超えた場合、`sqlite3.Connection.interrupt()` を用いて実行中のクエリを中断し、呼び出し元に `TimeoutError` を返す。これにより、ライタースレッドの恒久的なハングを防ぎ、システムの可用性を維持する。

  ## パラメータ詳細

  | 設定 | デフォルト | 説明 |
  |---|---|---|
  | `journal_mode` | `WAL` | 書き込みと読み取りの並行性を高める設定 |
  | `synchronous` | `NORMAL` | パフォーマンスと耐久性のバランス設定 |
  | `timeout` | `30.0` | データベースロック待機およびクエリ実行のタイムアウト閾値 |

  ## エラーハンドリング

  - **タイムアウト**: `TimeoutError` を送出する。
  - **接続失敗**: `sqlite3.Error` をキャッチし、適切にラップして再送出する。
  - **シャットダウン時**: ライタースレッドへの新規タスク投入を停止し、保留中のタスクを完了させてから接続を閉じる。

  ## エッジケース

  - **破損DB**: DBファイルが壊れている場合は、初期化時に検知しエラーとする。
  - **インメモリDB**: `:memory:` 指定時は、プロセスの生存期間中のみキャッシュが保持される。
