はじめに
Railsのバージョン7.0.71 が公開されました。パッチバージョンの更新なので大きな変更はないですが、一通り確認していきたいと思います。
第一弾として、今回は ActiveSupportの"Fix Cache::NullStore with local caching for repeated reads"2について確認していきます。
(※ 記事執筆中にv7.0.7.1が公開されました。v7.0.7から大きくは変わっていませんので、v7.0.7が終わり次第、記事にします)
時間が取れず、だいぶ時間が空いてしまいましたので、これ以上の確認は実施しません。お待ちしていた方にはお詫び申し上げます。
概要
v7.0.6だとActiveSupport::Cache::NullStore
で#with_local_cache
を使っているとき、値を設定していない項目を#read_multi
で2回読みだすとエラーが発生します。
値が設定されていないのであればnil
を返す方が適切であるため、v7.0.7でnil
を出力するように修正されました。
#with_local_cache
と#read_multi
が同時に使用される箇所があれば、バージョンアップに関わらず、動作が想定通りか確認してください。
経緯
Railsではキャッシュを利用する仕組みがいくつか用意されています。
この中で、今回のバージョンアップの対象になったのが、ActiveSupport::Cache::NullStore
です。
NullStore
はActiveSpport::Cache::Store
を継承しているため、値の保存と読出しのメソッドが実装されています。ですが、NullStore
は保存のメソッドを呼び出しても実際にはキャッシュしません。
開発時やテストのときに、プログラム中ではキャッシュへの保存を実行しているけどキャッシュの値を利用したくない、という場合に便利なクラスです。
値を保存しないとのことですが、NullStore
は#with_local_cache
を使うことで一時的にローカルのメモリに保存できるようになります。
v7.0.6では、NullStore
を使っているときに、1. 値が設定されていない項目を、2. #read
あるいは#read_multi
で読み込んだ後、3. さらに#read_multi
で読み込んだときにNoMethodError
が発生していました。
#read
がnil
を返すので同様にnil
を返してほしいところですがこのような動作になっていました。
なお、問題となっている部分のコードはv7.0.3から混入していることがコミット履歴から分かります3。
該当のコミット4はv7.0.3のCHANGELOGに記載がないもので、しれっとマージされているものなのだ、と勉強になりました。
バージョンアップに伴う変更点
#read_multi
でNoMethodError
になっていたところを、v7.0.7からはエラーを発生させずにnil
を出力するようになりました。
対処
バージョンアップするしないに関わらず、以下を確認した方がよいです。
-
#with_local_cache
を利用し、かつ、#read_multi
が使われている箇所を探してください。なければ問題ありません。 -
#read_multi
が値が設定されていないキーを読みだしたとき、NoMethodError
が発生するかnil
が返されるか、どちらを想定しているか確認してください。 -
NoMethodError
を想定している場合はv7.0.6であれば問題ありません。もし、v7.0.7にバージョンアップする場合には、エラーが発生しないことを前提とした処理に変更してください。
動作確認
AcviteSupport::Cache::NullStroe
の基本動作
NullStore
は値を保存しません。保存した項目を呼び出そうとするとnil
となります。
cache.write("name", "Taro")
result = cache.read("name")
puts "result = " + (result.nil? ? "nil" : result)
result = nil
#with_local_cache
のブロック内では値がキャッシュされます。
cache.with_local_cache do
cache.write("name", "Taro")
result = cache.read("name")
puts "result = " + result
end
result = Taro
未保存の項目を#read_multi
で読み込む
v7.0.6の場合は2回目の#read_multi
の呼び出しでNoMethodError
が生じます。
cache.with_local_cache do
cache.clear
cache.read_multi("name")
begin
cache.read_multi("name")
rescue Exception => e
puts "raise: " + e.class.to_s
end
end
raise: NoMethodError
一方、v7.0.7ではnil
が出力されます
cache.with_local_cache do
cache.clear
cache.read_multi("name")
result = cache.read_multi("name")
puts "result = " + result.to_s
end
result = {"name"=>nil}
リンク
動作確認用のコードと環境はこちらのリポジトリにまとめています。
コードの場所は<バージョン>/lib/samples/active_support_null_store.rb
となります。