Skip to content

Cache keys - recyclable by default? #517

@ryanvall

Description

@ryanvall

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
end

This 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
end

In 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
end

Which 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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions