active: true
derived: false
groups:
- BGIO
header: |
  実行中タスクの強参照セットによる追跡
level: 1.48
links:
- ARCH006: NQNGQUULw16h1cxj2M5I4pgAr3bNlRze6AMKu_rdo0s=
- REQ006: 3PN_I3D9BWCwGe4h19vSOVkDSeWNY3sM_fbWg0rwOfk=
normative: true
ref: ''
reviewed: jPMSTPLQFiDj1oLJEOMPrVO52kbaRlPJevFQkGKaUmQ=
status: accepted
text: |
  # 実行中タスクの強参照セットによる追跡

  ## コンテキストと課題

  `Spot` インスタンスは、バックグラウンドで実行中の保存タスク（`Future`）を内部のセットで管理しています。これはシャットダウン時や `flush()` 呼び出し時に、すべてのタスクが完了したかを確認するために必要です。この追跡において、強参照を使用すべきか、それとも GC を妨げない弱参照を使用すべきかを決定する必要があります。

  ## 判断基準

  * **Durability**: ユーザーコードが `Future` オブジェクトへの参照を即座に破棄した場合でも、タスクが途中で GC されることなく確実に完了まで実行されること。
  * **Waitability**: `flush()` 呼び出し時に、全ての未完了タスクを漏れなく検知し、待機できること。
  * **Determinism**: タスクの追跡ライフサイクルが、GC という非決定的なイベントではなく、タスクの完了という明確なイベントに同期していること。

  ## 検討した選択肢

  * **Option 1**: `weakref.WeakSet` を使用する。参照がなくなると自動的に削除されるが、待機すべきタスクが GC のタイミングで勝手に消えてしまうリスクがある。
  * **Option 2**: 通常の `set`（強参照）を使用し、タスク完了のコールバックによって明示的にセットから削除する。

  ## 決定事項

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

  タスクの追跡には通常の `set` を使用し、強参照によってタスクの生存を保証します。

  1. **生存保証**: `Spot` が強参照を保持することで、タスクが確実に完了まで実行されることを保証します。
  2. **待機可能性**: `WeakSet` で発生しうる「待機すべきタスクが勝手に消える」という不透明な挙動を排除します。
  3. **決定論的な挙動**: タスク削除のタイミングが完了コールバックに紐付くため、挙動が予測可能になり、デバッグやテストが容易になります。

  ## 影響・結果

  * **ポジティブ**:
      * タスクの完了が保証され、データの整合性が高まる。
      * `flush()` の挙動が正確になり、確実なドレインが可能になる。
  * **ネガティブ**:
      * コールバックが呼ばれないような致命的なバグが発生した場合に、メモリを占有し続けるリスクがある。ただし、`atexit` 等のシャットダウン機構によってプロセスレベルでの救済策が講じられているため、許容可能である。
