ActiveSupport の定数を Ractor 安全にするためのラップ追加
ActiveSupport が保持するレベルチェック用ラムダとデバッグモード判定用プロックを Ractor 共有可能 にラップし、マルチ Ractor 環境でも安全に利用できるようになりました。動作は従来と変わらず、内部ロジックへの影響はありません。
背景
このセクションでは、Ractor 環境での安全性確保が必要となった背景を示します。
ActiveSupport の EventReporter::LogSubscriber::LEVEL_CHECKS と StructuredEventSubscriber::DEBUG_CHECK は、ロガーのレベル判定やデバッグモード判定に使われる ラムダ/プロック で、どちらもインスタンス状態を保持しません。そのため Ractor 間で共有できる形にすることで、マルチ Ractor アプリケーションでも例外なく使用できることが期待されました。
技術的な変更
このセクションでは、実装上の具体的変更点とその影響を解説します。
LEVEL_CHECKS 定数の各ラムダが ActiveSupport::Ractors.shareable_lambda でラップされ、Ractor 共有可能になりました。変更前後のコードは以下の通りです。
LEVEL_CHECKS = {
- debug: -> (logger) { logger.debug? },
- info: -> (logger) { logger.info? },
- error: -> (logger) { logger.error? },
+ debug: ActiveSupport::Ractors.shareable_lambda(&-> (logger) { logger.debug? }),
+ info: ActiveSupport::Ractors.shareable_lambda(&-> (logger) { logger.info? }),
+ error: ActiveSupport::Ractors.shareable_lambda(&-> (logger) { logger.error? }),
}.freeze
DEBUG_CHECK 定数は ActiveSupport::Ractors.shareable_proc でラップされ、デバッグモード判定のプロックが Ractor 共有可能になりました。変更前後は次のとおりです。
-DEBUG_CHECK = proc { !ActiveSupport.event_reporter.debug_mode? }
+DEBUG_CHECK = ActiveSupport::Ractors.shareable_proc { !ActiveSupport.event_reporter.debug_mode? }
これらのラップは 状態を捕捉しない 現行のラムダ/プロックに対してのみ適用され、既存ロジックの呼び出し側は変更不要です。
設計判断
このセクションでは、変更に込められた設計上の意図とトレードオフを整理します。
既存定数を拡張する形 で Ractor 共有化を実装したため、外部 API はそのまま保持され、利用者がコードを変更する必要がありません。代替案として新たな定数名や設定項目を導入する案もありましたが、互換性とシンプルさが優先されました。
ラップは 状態を捕捉しない ラムダとプロックに限定して適用したため、Ractor へのコピーコストは最小限に抑えられます。また、shareable_lambda と shareable_proc の内部実装は変わらず、実行速度やエラーハンドリングに影響はありません。
まとめ
LEVEL_CHECKS と DEBUG_CHECK を Ractor 共有可能な形にラップしたことで、ActiveSupport のロギング機構はマルチ Ractor 環境でも安全に動作します。既存の呼び出しコードはそのままで、振る舞いは変わらないため、既存ユーザーへの影術リスクはありません。