active: true
derived: false
groups:
- HOOK
header: |
  HookBase 実装
level: 2.19
links:
- SPEC019: VdxSnFuMf9VXXiuwabp5uqHyenNLFJwqfF8iai4defM=
normative: true
ref: ''
references:
- path: src/beautyspot/hooks.py
  type: file
reviewed: q5GInQd4UkppaBtSs8qtL1y_xpDihjGclB5tr7NI3Jg=
text: |
  ## 実装概要

  タスク実行ライフサイクルに介入するインターフェース `HookBase` と、
  そのスレッドセーフ版 `ThreadSafeHookBase` の実装。
  `pre_execute`, `on_cache_hit`, `on_cache_miss` の各コールバックが提供される。
  `ThreadSafeHookBase` は `__init_subclass__` を利用し、サブクラスで定義された
  フックメソッドを自動的にロックでラップする。

  ## 設計判断

  ### __init_subclass__ による透過的ロッキング

  ユーザーが手動でロックを書く手間を省くため、メタクラス的なアプローチを採用。
  クラス定義時にフックメソッドを抽出し、`_wrap_with_lock` デコレータで包むことで、
  ユーザーコードを汚さずに完全な排他制御を実現している。

  ### RLock（再入可能ロック）の使用

  当初の `Lock` から `RLock` に変更された。
  サブクラスが `super().pre_execute(...)` のように親のメソッドを呼び出した際、
  同一スレッドが再度ロックを取得しようとしてデッドロックする問題を防ぐため。

  ## 実装メモ

  - `_wrap_with_lock` は `functools.wraps` を使い、元のメタデータを保持する
  - `ThreadSafeHookBase` は `__getattr__` をオーバーライドし、
    `super().__init__()` の呼び出し忘れに対して親切なエラーメッセージを返す
