active: true
derived: false
groups:
- MAINT
header: |
  MaintenanceService 実装
level: '2.20'
links:
- SPEC020: NTlW5X3cj5UrQb-SH3YhZG10AwptJvDUc3aUW4rIvWQ=
normative: true
ref: ''
references:
- path: src/beautyspot/maintenance.py
  type: file
reviewed: yuJPJoRCdq2O8TML3BGfMmaSKayUD23Ap7z0HZjjT0Y=
text: |
  ## 実装概要

  `MaintenanceService` クラスがDBとBlobストレージ間の整合性チェック、
  期限切れキャッシュの削除、孤立ファイルの検出といったガベージコレクション（GC）を担当。
  主にCLIの `beautyspot gc` コマンドから呼び出される。
  対象となる DB (`TaskDBMaintenable`) とストレージ (`BlobStorageMaintenable`) を受け取り、
  複数のフェーズに分けてクリーンアップを実行する。

  ## 設計判断

  ### 5フェーズのクリーンアッププロセス

  `clean_garbage()` は以下の順序で安全にGCを実行する：
  1. 期限切れDBレコードの削除
  2. Blobストレージの一時ファイル（`.spot_tmp`）のクリーンアップ
  3. 孤立したBlobファイル（DBに存在しないファイル）の特定
  4. 孤立ファイルの削除
  5. 空ディレクトリの剪定

  ### Grace Period (猶予期間) の導入

  実行中のタスクがBlobを書き込んだ直後で、まだDBにメタデータが保存されていない
  タイミングでGCが走ると、必要なファイルが孤立と誤認されるリスクがある。
  これを防ぐため、`orphan_grace_seconds`（デフォルト60秒）より新しいファイルは
  孤立判定から除外する設計とした。

  ## 実装メモ

  - 孤立ファイルの検出 `scan_garbage()` は、ストレージの全キーを列挙し、
    DBの `get_blob_keys()` との差分を取ることで行う
  - 複数プロジェクトを一括でGCするためのヘルパー `scan_orphan_projects()` も提供される
