-
Notifications
You must be signed in to change notification settings - Fork 447
Description
Hello! We are currently working on upgrading an existing application to Rails 6, and as a part of that process, are looking to take advantage of recyclable cache keys (introduced in rails/29092). I'm looking for some clarification as to why Jbuilder doesn't seem to be making use of that feature by default.
Given a model called Comment, and a cache block such as:
json.cache! ['v1', comment] do
# code
endThis is continuing to generate a key that, as part of it, includes the updated_at timestamp, eg: v1/comments/1-20211110225305129882, when I would have expected it to not include the timestamp. Checking out the code, Jbuilder is utilizing ActiveSupport::Cache.expand_cache_key to get the full key, which in turn is calling this internal retrieve_cache_key method:
https://github.com/rails/rails/blob/main/activesupport/lib/active_support/cache.rb#L112
It favors calling cache_key_with_version on the object (or if given an array, cache_key_with_version on each individual element). Additionally, if a version option is not explicitly given, it's not utilized when writing results to the cache either. This is in contrast to utilizing the Rails.cache API directly:
Rails.cache.fetch(['v1', comment]) do
# code
endIn this instance, the key is generated by calling normalize_key, which does just call cache_key on each element of the array:
https://github.com/rails/rails/blob/main/activesupport/lib/active_support/cache.rb#L352
Additionally, on writes, the version is merged in by default, even if not given:
https://github.com/rails/rails/blob/main/activesupport/lib/active_support/cache.rb#L498
Interestingly enough, in the original pull request for recyclable cache keys, the expand_cache_key method did not include any logic to call cache_key_with_version. It was added later in this commit to retain existing behavior for other purposes.
With all that said, is it potentially a bug that jbuilder isn't utilizing versioned keys now? Or is all this behavior intentional? Right now, the only way I see to get recyclable cache keys to work is to explicitly call/provide cache_key for each element, along with the version:
json.cache! ['v1', comment.cache_key], version: comment.cache_version do
# code
endWhich isn't as concise as the Rails.cache.fetch/Rails.cache.read API, and is prone to issues if either cache_key or the version argument are forgotten. Thanks for any insight/clarification!