lib/second_level_cache/mixin.rb
# frozen_string_literal: true
module SecondLevelCache
module Mixin
extend ActiveSupport::Concern
module ClassMethods
attr_reader :second_level_cache_options
delegate :logger, :cache_store, :cache_key_prefix, to: SecondLevelCache
def second_level_cache(options = {})
@second_level_cache_enabled = true
@second_level_cache_options = options
@second_level_cache_options[:version] ||= 0
@second_level_cache_options[:expires_in] ||= 1.week
relation.class.send :prepend, SecondLevelCache::ActiveRecord::FinderMethods
prepend SecondLevelCache::ActiveRecord::Core
end
def second_level_cache_enabled?
if defined? @second_level_cache_enabled
@second_level_cache_enabled == true && SecondLevelCache.cache_enabled?
else
false
end
end
def without_second_level_cache(&blk)
SecondLevelCache.without_second_level_cache(&blk) if blk
end
# Get MD5 digest of this Model schema
# http://api.rubyonrails.org/classes/ActiveRecord/Core/ClassMethods.html#method-i-inspect
def cache_version
return @cache_version if defined? @cache_version
# This line is copy from:
# https://github.com/rails/rails/blob/f9a5f48/activerecord/lib/active_record/core.rb#L236
attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
model_schema_digest = Digest::MD5.hexdigest(attr_list)
@cache_version = "#{second_level_cache_options[:version]}/#{model_schema_digest}"
end
def second_level_cache_key(id)
"#{cache_key_prefix}/#{table_name.downcase}/#{id}/#{cache_version}"
end
def read_second_level_cache(id)
return unless second_level_cache_enabled?
RecordMarshal.load(SecondLevelCache.cache_store.read(second_level_cache_key(id)))
end
def expire_second_level_cache(id)
return unless second_level_cache_enabled?
SecondLevelCache.cache_store.delete(second_level_cache_key(id))
end
end
def second_level_cache_key
klass.second_level_cache_key(id)
end
def klass
self.class.base_class
end
def expire_second_level_cache
return unless klass.second_level_cache_enabled?
SecondLevelCache.cache_store.delete(second_level_cache_key)
end
def write_second_level_cache
return unless klass.second_level_cache_enabled?
marshal = RecordMarshal.dump(self)
expires_in = klass.second_level_cache_options[:expires_in]
SecondLevelCache.cache_store.write(second_level_cache_key, marshal, expires_in: expires_in)
end
alias_method :update_second_level_cache, :write_second_level_cache
end
end