IDC的更新机制基本上是靠after_commit :expire_cache来做的,它使得commit后自动删掉对应“前缀+id”的缓存

至于为什么要after_commit而非after_save、after_update,那是因为commit只会有一次,而且只在整个transaction成功后才有。如果删缓存后,transaction中接下来的某个对象不合格导致rollback而使数据库没更新,那么缓存就白删了

相关源码如下

identity_cache-0.5.1/lib/identity_cache/query_api.rb

module IdentityCache
  module QueryAPI
    extend ActiveSupport::Concern

    included do |base|
      base.after_commit :expire_cache
    end

    module ClassMethods

      def fetch_by_id(id, options={})
        # ...
        IdentityCache.fetch(rails_cache_key(id)){ coder_from_record(object = resolve_cache_miss(id)) }
        # ...
      end
    end

    def expire_cache
      expire_primary_index
      expire_attribute_indexes
      true
    end

    def expire_primary_index
      return unless self.class.primary_cache_index_enabled

      IdentityCache.logger.debug do
        extra_keys =
          if respond_to?(:updated_at)
            old_updated_at = old_values_for_fields([:updated_at]).first
            "expiring_last_updated_at=#{old_updated_at}"
          else
            ""
          end

        "[IdentityCache] expiring=#{self.class.name} expiring_id=#{id} #{extra_keys}"
      end

      IdentityCache.cache.delete(primary_cache_index_key)
    end


identity_cache-0.5.1/lib/identity_cache/cache_key_generation.rb

module IdentityCache
  module CacheKeyGeneration
    extend ActiveSupport::Concern
    DEFAULT_NAMESPACE = "IDC:#{CACHE_VERSION}:".freeze

    module ClassMethods
      def rails_cache_key(id)
        "#{prefixed_rails_cache_key}#{id}"
      end
    end

    def primary_cache_index_key
      self.class.rails_cache_key(id)
    end