./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'