active: true
derived: false
groups:
- MAINT
header: |
  メンテナンス操作のためのサービスレイヤー
level: 1.22
links:
- ARCH010: fI3ChnJRbqIhdRSivmb1UxR5M9l1VFI4CmnTPt7dAKY=
- REQ010: Zx8DGaEjJ3NxeBVjpah5jdit-c1h1rfI-n6DmY7_zG0=
normative: true
ref: ''
reviewed: rpj6uA0KDqeWoyNJpJ6odiVUJnb7Hl9r7DjNLCy9N-8=
status: accepted
text: |
  # メンテナンス操作のためのサービスレイヤー

  ## コンテキストと課題

  現在、`src/beautyspot/cli.py` には以下のビジネスロジックが直接記述されています：
  1.  **Pruning**: タイムスタンプに基づく古いタスクの削除。
  2.  **Cleaning**: 孤立した Blob ファイルの特定と削除（ガベージコレクション）。

  これらのロジックは `sqlite3` ドライバに直接アクセスしたり、ファイルパスを操作したりしており、`TaskDB` や `BlobStorageBase` の抽象化をバイパスしています。これにより、CLI が SQLite やローカルファイルストレージの詳細に密結合し、他のインターフェース（スクリプトや Web UI）から同じロジックを再利用できないという問題が発生しています。また、S3 などの外部ストレージに対する「掃除」機能の実装も困難になっています。

  ## 判断基準

  * **Decoupling**: CLI を特定のデータベース実装やファイルシステム詳細から切り離すこと。
  * **Reusability**: メンテナンスロジック（整理や掃除）をプログラムから、あるいは Dashboard からも利用可能にすること。
  * **Abstraction Support**: S3 などの異なるストレージバックエンドでも、一貫したガベージコレクションが行えるようにすること。

  ## 検討した選択肢

  * **Option 1**: メンテナンスロジックを CLI に残したままにする。
  * **Option 2**: 全てのロジックを `Spot` クラスに追加する。
  * **Option 3**: 専用のサービスレイヤー `MaintenanceService` を新設し、管理ロジックを分離する。

  ## 決定事項

  採用した選択肢: **Option 3**.

  メンテナンスロジックを `cli.py` から抽出し、専用の **`MaintenanceService`** (`src/beautyspot/maintenance.py`) に移動します。

  `Spot` クラスはアプリケーションの実行コンテキストとキャッシュ制御に集中させ、メンテナンス（行政的タスク）は別の関心事として分離します。

  * **`MaintenanceService`**: レコードの整理、孤立した Blob の掃除、履歴の照会などを担当。`TaskDB` と `BlobStorageBase` を調整（Orchestrate）する。
  * **`Spot`**: 実行時の登録 (`mark`) と実行 (`run`) に専念する。

  ## 影響・結果

  * **ポジティブ**:
      * **関心の分離**: 実行時ロジック (`Spot`) を軽量に保ちつつ、管理ロジックを独立して進化させることができる。
      * **テスト容易性**: CLI を起動することなく、メンテナンスロジックのユニットテストが可能になる。
      * **再利用性**: 整理や掃除を他のスクリプトや Dashboard からトリガーできる。
      * **抽象化の恩恵**: バックエンドが `list_keys` 等を実装していれば、S3 等でも自動的に GC がサポートされる。
  * **ネガティブ**:
      * **インターフェースの拡張**: メンテナンス支援のため、`TaskDB` や `BlobStorageBase` に新たなメソッド（`list_keys`, `get_blob_refs` 等）を追加する必要がある。
