メソッド実行結果をキャッシュする
Rubyオブジェクトのメソッド実行結果をキャッシュするユーティリティを書きました。
require "fileutils" require 'file-lock' require 'kconv' require 'yaml' module Cache # # メソッドの実行結果をYAMLファイルにキャッシュする # delegate 実行結果をキャッシュするオブジェクト # enable キャッシュを利用するかどうか。 # range キャッシュの有効期限。秒で指定 # cache_file キャッシュファイル # regex キャッシュ対象メソッド # class YAMLCache def initialize(delegate, enable, range, cache_file, regex=".*") @delegate = delegate @range = range @cache_file = cache_file @regex = regex @enable = enable end def method_missing(name, *args ) return @delegate.send( name, *args ) if ( !name.to_s.match(@regex) ) flock = FileLock.new(@cache_file + ".lock") current = Time.new res = nil flock.writelock(){ # キャッシュがあればキャッシュから読む if ( @enable && File.exist?(@cache_file) && current.to_i < (File.mtime(@cache_file).to_i + @range) ) res = YAML.load_file @cache_file elsif res = @delegate.send( name, *args ) File.open( @cache_file, "w" ) { |f| f.write( YAML.dump(res) ) } File.utime(current, current, @cache_file) end } return res end end end
動作確認。
#動作確認 service = Cache::YAMLCache.new(Test.new, true, 3, "../test-cache.yaml", "search") puts service.search("b", "xxxx1") # 初回。結果がキャッシュされる sleep(1) puts service.search("b", "xxxx2") # キャッシュが有効期間内なのでキャッシュから結果が返される。 sleep(5) puts service.search("b", "xxxx3") # 有効期限が過ぎたのでキャッシュは無効 # 正規表現にマッチしないメソッドの戻り値はキャッシュされない puts service.hoge("c", "xxxx1") puts service.hoge("c", "xxxx2")
実行結果です。
search_bxxxx1 search_bxxxx1 search_bxxxx3 hoge_cxxxx1 hoge_cxxxx2