module Scrivito # This module manages storage of different kind of cache data. module CmsDataCache VERSION = 'v3'.freeze class << self def cache Thread.current[:scrivito_cms_data_cache_chain] ||= Cache::RamStore.new(next_store: first_level_cache, cache_prefix: VERSION) end def cache_path=(path) clear_cache_chain @cache_path = path end def first_level_cache @first_level_cache ||= Cache::FileStore.new(path: @cache_path, next_store: second_level_cache) end attr_reader :second_level_cache def second_level_cache=(cache_store) clear_cache_chain @second_level_cache = cache_store end SCHEMA = { obj_data: 'obj/#{cache_id}/#{index}/#{key}', content_state_node: 'csn/#{content_state_id}', workspace_state: 'wrkstt/#{workspace_id}', tag_data: 'tagd/#{tag}' } SCHEMA.each do |name, schema| params = schema.scan(/\#{([^}]+)}/).map(&:first) params_code = params.map(&:to_s).join(",") # using eval instead of define_method for performance reasons class_eval(<<-END, __FILE__, __LINE__ + 1) def read_#{name}(#{params_code}) cache.read("#{schema}") end END class_eval(<<-END, __FILE__, __LINE__ + 1) def write_#{name}(#{params_code}, data, **options) if data == nil raise InternalError, "tried to write nil into #{schema}" end cache.write("#{schema}", data, **options) end END # for test purposes class_eval(<<-END, __FILE__, __LINE__ + 1) def evict_#{name}(#{params_code}) cache.write("#{schema}", nil) end END end def write_data_to_tag(data) tag = Digest::SHA1.base64digest(Marshal::dump(data)) write_tag_data(tag, data) tag end def read_data_from_tag(tag) raise ArgumentError, 'tag can not be nil' if tag.nil? read_tag_data(tag) end def clear_request_cache cache.clear end private def clear_cache_chain Thread.current[:scrivito_cms_data_cache_chain] = nil @first_level_cache = nil @second_level_cache = nil end end end end