---
title: Service Layer for Maintenance Operations
status: Accepted
date: 2026-02-16
context: Decoupling Administrative Logic from CLI
---

# Service Layer for Maintenance Operations

## Context and Problem Statement / コンテキスト

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

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

## Decision Drivers / 要求

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

## Considered Options / 検討

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

## Decision Outcome / 決定

Chosen option: **Option 3**.

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

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

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

## Consequences / 決定

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