`Rails.cache.clear` で FileStore のキャッシュが削除されなかった話

Published: 2021/9/11


問題

capistrano でのデプロイの度に、 Rails.cache.clear を実行していたのだけれども、ActiveSupport::Cache::FileStore のファイルが 削除されていないことがあったりしたので、その原因を調査した際の備忘録。

原因

def clear(options = nil)
  root_dirs = (Dir.children(cache_path) - GITKEEP_FILES)
  FileUtils.rm_r(root_dirs.collect { |f| File.join(cache_path, f) })
rescue Errno::ENOENT, Errno::ENOTEMPTY
end

出典:

ここにあるように、 ActiveSupport::Cache::FileStore.clear メソッドは、 Errno::ENOENTErrno::ENOTEMPTY の例外が発生した場合には、しれっとそれを握り潰して正常終了する。

さらには、この FileUtils.rm_r のコマンドは、これを実行している最中にそのディレクトリの中にファイルを作成したりしていると、 Errono::ENOTEMPTY が発生してしまう。

自分の場合だと、

  1. キャッシュディレクトリを linked_dir に指定
  2. デプロイ直後にキャッシュクリアを実行

していたため、 puma が新しいバージョンのアプリで起動しようとして、 bootsnap のキャッシュ(FileStore のデフォルトのキャッシュパスと同じ所tmp/cacheに生成される)をもりもり生成するタイミングと、Rails.cache.clear のタイミングが被ってしまい、結果 Errono::ENOTEMPTY が発生しそこでキャッシュの削除がアボートして正常終了する、という挙動になっていた。

対策

Rails.cache.clear は、 puma の restart など、アプリの立ち上がり処理のタイミングを避けて実行する。 もしくは、キャッシュディレクトリは、デプロイの度に新しいものを用意するようにする。

サマリー FAQ


Tags: rails

関連記事