ActiveSupport::Cache のインストゥルメンテーションとローカルキャッシュロジックのリファクタリング
ActiveSupport::Cache が内部ヘルパー _instrument を廃止し、Logger#debug のブロック形式へ置き換えると同時に、ローカルキャッシュでの increment / decrement 実装を簡素化し、不要となった bypass_local_cache メソッドを削除しました。これによりコードの重複が減り可読性が向上し、振る舞いはそのまま維持されています。
背景
ActiveSupport::Cache のインストゥルメンテーションは、キャッシュ操作のトレーシングとデバッグ情報出力を担当していましたが、 _instrument ヘルパーが複数箇所で重複して実装されていたためメンテナンスコストが増大していました。ローカルキャッシュ側でも bypass_local_cache が残存し、実質的に利用されていない状態が続いていたことが指摘されました。これらの余計な抽象化を取り除くことで、コードベースのシンプルさと一貫性を高めることが目的です。
技術的な変更
activesupport/lib/active_support/cache.rb では instrument メソッドが直接 logger&.debug ブロックを用いてデバッグ文字列を遅延生成し、silence? のチェックのみ残しています。さらに payload を組み立てて ActiveSupport::Notifications.instrument を呼び出す形に統一し、_instrument ヘルパー自体を削除しました。
def instrument(operation, key, options = nil, &block)
unless silence?
logger&.debug do
debug_key = ": #{key}" if key
debug_options = " (#{options.inspect})" unless options.blank?
"Cache #{operation}#{debug_key}#{debug_options}"
end
end
payload = { store: self.class.name, key: key }
payload.merge!(options) if options.is_a?(Hash)
ActiveSupport::Notifications.instrument("cache_#{operation}.active_support", payload) do
block&.call(payload)
end
end
activesupport/lib/active_support/cache/memory_store.rb では、cleanup 内で呼び出していた _instrument が instrument に置き換えられ、同一インターフェースで動作するようになっています。
instrument(:cleanup, nil, size: @data.size) do
keys = synchronize { @data.keys }
# ...
end
activesupport/lib/active_support/cache/strategy/local_cache.rb では increment と decrement がローカルキャッシュの有無に関わらず super を直接呼び出すよう変更され、bypass_local_cache 呼び出しが除去されました。また、同メソッド自体が削除され、代わりに use_temporary_local_cache が残ります。
def increment(name, amount = 1, **options)
return super unless local_cache
value = super
write_cache_value(name, value, raw: true, **options)
value
end
テストコードも同様に更新され、bypass_local_cache の呼び出しはすべて use_temporary_local_cache(nil, …) に置き換えられました。加えて increment と decrement のミスケース(ローカルキャッシュがミスしたとき)の検証が新たに追加されています。
設計判断
ヘルパーメソッド _instrument の削除 は、内部実装の重複を無くすための明確な判断です。公開 API を変えずに内部だけを整理することで、既存利用者への影響を回避しつつコードの見通しを良くしています。さらに Logger#debug のブロック形式へ置換えることで、デバッグ文字列の生成が実際にデバッグ出力が必要なときだけ行われ、軽微なパフォーマンス改善とコードの簡潔化が同時に実現されています。
bypass_local_cache の廃止 は、ローカルキャッシュを一時的に無効化する機能が use_temporary_local_cache に統合されたことに起因します。余分なメソッドを減らすことで API のサイズが小さくなり、メンテナンス対象が減ります。一方で同名メソッドを直接呼び出していた内部コードはすべて更新されているため、振る舞いの変更はありません。
increment / decrement の実装簡素化 は、ローカルキャッシュの有無に関係なく基本ロジックを super に委譲し、結果だけをローカルに書き戻すという明快な流れに統一されたことがポイントです。これによりコードパスが減り、バグ発生リスクが低減します。
まとめ
本リファクタリングは ActiveSupport::Cache の内部実装を整理し、不要なヘルパーとメソッドを除去することで可読性と保守性を向上させました。動作は従来と同等であり、テストスイートも新しいロジックを検証する形で拡充されています。この変更により、将来の機能追加やバグ修正がシンプルなコードベース上で行える基盤が整いました。