./lib/lux/cache/cache.rb in lux-fw-0.5.37 vs ./lib/lux/cache/cache.rb in lux-fw-0.6.2

- old
+ new

@@ -1,103 +1,142 @@ -# frozen_string_literal: true - module Lux + OPTS ||= Struct.new 'LuxCacheOpts', :ttl, :force, :if, :unless, :speed, :delete_if_empty + class Cache - def initialize - @server = Lux::Cache::MemoryCache.new + def initialize server_name = nil + self.server= server_name || :memory end # sert cache server # Lux.cache.server = :memory # Lux.cache.server = :memcached # Lux.cache.server = Dalli::Client.new('localhost:11211', { :namespace=>Digest::MD5.hexdigest(__FILE__)[0,4], :compress => true, :expires_in => 1.hour }) def server= name - @server = if name.is_a?(Symbol) - if name == :memcached - require 'dalli' - Dalli::Client.new('127.0.0.1:11211', { :namespace=>Digest::MD5.hexdigest(__FILE__)[0,4], :compress => true, :expires_in => 1.hour }) - else - "Lux::Cache::#{name.to_s.classify}Cache".constantize.new - end + @server = + if name.is_a?(Symbol) + require_relative 'lib/%s_server' % name + @server = ('lux/cache/%s_server' % name).classify.constantize.new else name end - - fetch('cache-test') { true } end def server @server end def read key return nil if (Lux.current.no_cache? rescue false) + key = generate_key key + log_get "Cache.read #{key}" @server.get(key) end alias :get :read def read_multi *args @server.get_multi(*args) end alias :get_multi :read_multi - def write key, data, ttl=nil + def write key, data, ttl = nil + ttl = ttl[:ttl] || ttl[:expires_at] if ttl.class == Hash ttl = ttl.to_i if ttl + key = generate_key key + Lux.log %[ Cache.write "#{key}", at: #{Lux.app_caller}].yellow @server.set(key, data, ttl) end alias :set :write def delete key, data=nil + key = generate_key key + + Lux.log do + if Lux.config[:show_cache_log] + %[ Cache.delete "#{key}", at: #{Lux.app_caller}].yellow + end + end + @server.delete(key) end def fetch key, opts={} + key = generate_key key + opts = { ttl: opts } unless opts.is_a?(Hash) - opts = opts.to_opts(:ttl, :force, :log, :if) + opts = OPTS.new **opts return yield if opts.if.is_a?(FalseClass) opts.ttl = opts.ttl.to_i if opts.ttl - opts.log ||= Lux.config(:log_to_stdout) unless opts.log.class == FalseClass opts.force ||= Lux.current.try(:no_cache?) unless opts.force.class == FalseClass @server.delete key if opts.force - Lux.log " Cache.fetch.get #{key} (ttl: #{opts.ttl.or(:nil)})".green if opts.log + log_key_name = "Cache.fetch.get #{opts.compact.to_jsonc}:#{key.trim(30)}" + log_get log_key_name data = @server.fetch key, opts.ttl do - speed = Lux.speed { data = yield } + opts.speed = Lux.speed { data = yield } + Lux.log " #{log_key_name}, at: #{Lux.app_caller}".yellow + Marshal.dump data + end - Lux.log " Cache.fetch.SET #{key} len:#{data.to_s.length} (#{speed})".red if opts.log + Marshal.load(data).tap do |out| + if opts.delete_if_empty && out.empty? + @server.delete key + end + end + end - data + # lock execution of a block for some time and allow only once instance running in time slot + # give some block 3 seconds to run, if another instance executes same block after 1 second, if will wait 2 seconds till it wil continue + # Lux.cache.lock 'some-key', 3 do ... + def lock key, time + key = "syslock-#{key}" + cache_time = Lux.cache.get key + + if cache_time && cache_time > (Time.monotonic - time) + diff = time - (Time.monotonic - cache_time) + sleep diff.abs + else + Lux.cache.set(key, Time.monotonic, time) end - data + yield end + def clear + @server.clear + end + def is_available? set('lux-test', 9) get('lux-test') == 9 end def generate_key *data + if data[0].class == String && !data[1] + return data[0] + end + keys = [] for el in [data].flatten + keys.push el.class.to_s keys.push el.id if el.respond_to?(:id) if el.respond_to?(:updated_at) - keys.push el.updated_at - elsif el.respond_to?(:created_at) - keys.push el.created_at + keys.push el.updated_at.to_f + elsif el.respond_to?(:id) + keys.push el.id else keys.push el.to_s end end key = keys.join('-') + Crypt.sha1(key) end def []= key, value @server.set key.to_s, value @@ -106,9 +145,22 @@ def [] key @server.get key.to_s end + def log_get name + if Lux.env.screen_log? + if Lux.current.params[:lux_show_cache_get] + Lux.config[:show_cache_log] = true + end + + if Lux.config[:show_cache_log] + Lux.log " Cache.get #{name}, at: #{Lux.app_caller}".green + else + if Lux.current.once(:show_cache_log) + Lux.log " Cache.get info is suppressed: enable? -> #{Lux.current.nav.base}#{Lux.current.request.path}?lux_show_cache_get=true".green + end + end + end + end end end - -require_relative 'lib/memory'