---
title: バックグラウンドループのライフサイクル管理とGC時のデータロスト対策
status: Accepted
date: 2026-02-24
context: Balancing Performance and Data Integrity
---

# バックグラウンドループのライフサイクル管理とGC時のデータロスト対策

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

`Spot` クラスは非同期のキャッシュ保存を構造的に直列化するため、内部で専用の `asyncio` ループを実行するスレッド (`_BackgroundLoop`) を保持しています。インスタンスがガベージコレクション (GC) によって破棄される際、未保存のキャッシュデータを厳密に待機してしまうと、メインスレッドを予測不能なタイミングでフリーズさせたり、デッドロックを引き起こす危険性があります。

そのため、これまでは安全を優先し、GC 時にはタスクをキャンセルしてリソースを解放する設計となっていました。しかし、この設計では一時的なスコープで `Spot` を使用した場合、GC のタイミングによってキャッシュデータが失われるという課題がありました。

## Decision Drivers / 要求

* **Safety**: GC 時の予期せぬブロッキングやデッドロックを回避し、アプリケーションの安定性を損なわないこと。
* **Data Integrity**: バックグラウンドに投入された保存タスクを、可能な限り完了させること。
* **Predictability**: ユーザーがライフサイクルを制御できる手段を提供し、挙動を明確にすること。

## Considered Options / 検討

* **Option 1**: GC 時に常に保存完了を待機する。フリーズやデッドロックのリスクが高い。
* **Option 2**: GC 時に即座にタスクをキャンセルする。データロストのリスクがある。
* **Option 3**: `atexit` によるグローバルな安全網を導入し、プロセス終了時に未完了タスクをドレインする。あわせて明示的な管理を推奨する。

## Decision Outcome / 決定

Chosen option: **Option 3**.

1. **`atexit` によるグローバルな安全網の追加**: 
   `weakref.WeakSet` を用いて起動中のバックグラウンドループを追跡し、プロセス終了時 (`atexit`) に `wait=True` でドレイン（残存タスクの処理）を行うフックを実装します。プロセス終了時であれば、メインスレッドをブロックしてもデッドロックの危険性が低いためです。
2. **明示的なリソース管理の推奨**: 
   `Spot` インスタンスは長寿命なオブジェクトとして扱うか、コンテキストマネージャ (`with`) または `shutdown(wait=True)` による明示的な管理を行うべきであることを周知します。

## Consequences / 決定

* **Positive**:
    * 一時的なスコープで `Spot` を使った場合でも、アプリ終了時まではデータが救済される可能性が高まる。
    * メインスレッドの安全性（GC 時のフリーズ回避）と、キャッシュ保存の確実性のバランスが取れる。
* **Negative**:
    * `atexit` 時に大量の未完了タスクがあると、プロセス終了に時間がかかる場合がある。
