Uploaded image for project: 'Mongoid'
  1. Mongoid
  2. MONGOID-4680

Add a cache_version implementation to be used with rails 5.2 caching

    • Type: Icon: Improvement Improvement
    • Resolution: Fixed
    • Priority: Icon: Minor - P4 Minor - P4
    • 9.1.0
    • Affects Version/s: 7.0.2
    • Component/s: None
    • Environment:
      Rails 5.2.2
      Mongoid 7.0.2
    • Needed
    • Hide

      1. What would you like to communicate to the user about this feature?

      As of Mongoid 9.1, cache keys for models with timestamps no longer include the version in the key itself. This may result in caches being invalidated when this change is first deployed. If this is a concern, you can redefine the `cache_version` method to return nil, which will cause the original cache keys to be generated instead.

      def cache_version = nil

      2. Would you like the user to see examples of the syntax and/or executable code and its output?

      Yes, please, as given above.

       

      3. Which versions of the driver/connector does this apply to?

      This only applies to Mongoid versions 9.1 and greater.

      Show
      1. What would you like to communicate to the user about this feature? As of Mongoid 9.1, cache keys for models with timestamps no longer include the version in the key itself. This may result in caches being invalidated when this change is first deployed. If this is a concern, you can redefine the `cache_version` method to return nil, which will cause the original cache keys to be generated instead. def cache_version = nil 2. Would you like the user to see examples of the syntax and/or executable code and its output? Yes, please, as given above.   3. Which versions of the driver/connector does this apply to? This only applies to Mongoid versions 9.1 and greater.

      Rails 5.2 implements a #cache_version method that gets called by ActiveSupport caching. The method simply gets a usec-formatted timestamp String from the updated_at timestamp.

      This method is absent from mongoid. Therefore, when using a simple cache directive in a view:

      <% cache @post do %>
        <%= render @post %>
      <% end %>

      ... the code will fail with a stack level too deep exception. The exception is caused by ActiveSupport::Cache#expanded_version, which is a method deep down the call chain of the "cache" method called in the view above. This method first attempts to call #cache_version on the model, which will fail with mongoid, since it lacks this method. (With ActiveRecord, we would exit out here, returning the timestamp.) Next, it checks if the argument is an Array; it is not, so we move on. Next, it checks if the model responds to #to_a. Our model does respond to #to_a, returning an array with the sole element being the model. The method then calls itself again recursively on that array. On the next iteration, #expanded_version fails again since Array does not implement that method. Next, it checks if the argument is an Array, and now it is, so it calls itself again for each element of the Array. Now, we have an infinitely recursive loop of the model being converted to an Array and placed inside more Arrays, until we get a "Stack level too deep" exception.

      For our project, I've patched the code as follows:

      module Mongoid
        module Document
          def cache_version
            updated_at.utc.to_s(:usec)
          end
        end
      end

      However, this is obviously not a suitable solution for the project as a whole, since only models with Mongoid::Timestamps will be able to access an updated_at timestamp. I'm not sure how you want to solve this, but I do believe that Mongoid should at least return nil for this method if the timestamp is not present in order to retain compatibility with ActiveRecord code inside ActiveSupport's caching code.

            Assignee:
            jamis.buck@mongodb.com Jamis Buck
            Reporter:
            dan@cacheventures.com Daniel Arnold
            Votes:
            0 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated:
              Resolved: