だから私は考え、考え、そして Mechanize と VCR のソース コードを見て、私は本当に問題を考えすぎているだけだと判断しました。以下は私のニーズにぴったりです。(私は DataMapper を使用していますが、それを ActiveRecord モデルに変換するのは簡単です):
class WebCache
include DataMapper::Resource
property :id, Serial
property :serialized_key, Text
property :serialized_value, Text
property :created_at, DateTime
property :updated_at, DateTime
def with_db_cache(akey)
serialized_key = YAML.dump(akey)
if (r = self.all(:serialized_key => serialized_key)).count != 0
# cache hit: return the de-serialized value
YAML.load(r.first.serialized_value)
else
# cache miss: evaluate the block, serialize and cache the result
yield(akey).tap {|avalue|
self.create(:serialized_key => serialized_key,
:serialized_value => YAML.dump(avalue))
}
end
end
end
使用例:
def fetch(uri)
WebCache.with_db_cache(uri) {|uri|
# arrive here only on cache miss
Net::HTTP.get_response(URI(uri))
}
end
解説
私は以前、適切な Web キャッシング スキームは、Cache-Control、If-Modified-Since などのヘッダー フィールドを観察して尊重し、タイムアウトやその他の Web 病理を自動的に処理すると信じていました。しかし、実際の Web ページを調べたところ、真に静的なデータは頻繁に短いキャッシュ時間でマークされていることが明らかになりました。したがって、何かをキャッシュする期間と、失敗したクエリをいつ再試行するかを呼び出し元に決定させる方が理にかなっています。
その時点で、コードは非常に単純になりました。
道徳:あなたの問題について考えすぎないでください。