0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Rails v7.0.7対応 ActiveSupport (Fix Cache::NullStore with local caching for repeated reads)

Last updated at Posted at 2023-08-24

はじめに

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です。

NullStoreActiveSpport::Cache::Storeを継承しているため、値の保存と読出しのメソッドが実装されています。ですが、NullStoreは保存のメソッドを呼び出しても実際にはキャッシュしません。
開発時やテストのときに、プログラム中ではキャッシュへの保存を実行しているけどキャッシュの値を利用したくない、という場合に便利なクラスです。

値を保存しないとのことですが、NullStore#with_local_cacheを使うことで一時的にローカルのメモリに保存できるようになります。

v7.0.6では、NullStoreを使っているときに、1. 値が設定されていない項目を、2. #readあるいは#read_multiで読み込んだ後、3. さらに#read_multiで読み込んだときにNoMethodErrorが発生していました。
#readnilを返すので同様にnilを返してほしいところですがこのような動作になっていました。

なお、問題となっている部分のコードはv7.0.3から混入していることがコミット履歴から分かります3
該当のコミット4はv7.0.3のCHANGELOGに記載がないもので、しれっとマージされているものなのだ、と勉強になりました。

バージョンアップに伴う変更点

#read_multiNoMethodErrorになっていたところを、v7.0.7からはエラーを発生させずにnilを出力するようになりました。

対処

バージョンアップするしないに関わらず、以下を確認した方がよいです。

  1. #with_local_cacheを利用し、かつ、#read_multiが使われている箇所を探してください。なければ問題ありません。
  2. #read_multiが値が設定されていないキーを読みだしたとき、NoMethodErrorが発生するかnilが返されるか、どちらを想定しているか確認してください。
  3. 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となります。

  1. CHANGELOG

  2. Merge pull request #48868 from fatkodima/backport-45728

  3. Comparing Changes between 7.0.2.4 and 7.0.3

  4. Merge pull request #44366 from avalanche123/patch-1

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?