Class: RedisMemo::Cache

Inherits:
ActiveSupport::Cache::RedisCacheStore
  • Object
show all
Defined in:
lib/redis_memo/cache.rb

Defined Under Namespace

Classes: Rescuable

Constant Summary collapse

@@redis =
nil
@@redis_store =
nil
@@redis_store_error_handler =
proc do |method:, exception:, returning:|
  RedisMemo::DefaultOptions.redis_error_handler&.call(exception, method)
  RedisMemo::DefaultOptions.logger&.warn(exception.full_message)
   if exception.is_a?(Redis::BaseConnectionError)
    RedisMemo.__send__(:incr_connection_attempts)
  end
   if RedisMemo::ThreadLocalVar.raise_error
    raise RedisMemo::Cache::Rescuable
  end
   returning
end

Class Method Summary collapse

Class Method Details

.local_cacheObject

We use our own local_cache instead of the one from RedisCacheStore, because the local_cache in RedisCacheStore stores a dumped ActiveSupport::Cache::Entry object – which is slower comparing to a simple hash storing object references



57
58
59
# File 'lib/redis_memo/cache.rb', line 57

def self.local_cache
  RedisMemo::ThreadLocalVar.local_cache
end

.local_dependency_cacheObject



61
62
63
# File 'lib/redis_memo/cache.rb', line 61

def self.local_dependency_cache
  RedisMemo::ThreadLocalVar.local_dependency_cache
end

.read_multi(*keys, raw: false, raise_error: false) ⇒ Object

RedisCacheStore doesn’t read from the local cache before reading from redis



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/redis_memo/cache.rb', line 86

def read_multi(*keys, raw: false, raise_error: false)
  return {} if keys.empty?

  RedisMemo::ThreadLocalVar.raise_error = raise_error

  local_entries = local_cache&.slice(*keys) || {}

  keys_to_fetch = keys
  keys_to_fetch -= local_entries.keys unless local_entries.empty?
  return local_entries if keys_to_fetch.empty?

  remote_entries = redis_store.read_multi(*keys_to_fetch, raw: raw)
  local_cache&.merge!(remote_entries)

  if local_entries.empty?
    remote_entries
  else
    local_entries.merge!(remote_entries)
  end
end

.redisObject



34
35
36
37
38
39
40
41
# File 'lib/redis_memo/cache.rb', line 34

def self.redis
  @@redis ||=
    if RedisMemo::DefaultOptions.connection_pool
      RedisMemo::ConnectionPool.new(**RedisMemo::DefaultOptions.connection_pool)
    else
      RedisMemo::DefaultOptions.redis
    end
end

.redis_storeObject



43
44
45
46
47
48
49
50
51
# File 'lib/redis_memo/cache.rb', line 43

def self.redis_store
  @@redis_store ||= new(
    compress: RedisMemo::DefaultOptions.compress,
    compress_threshold: RedisMemo::DefaultOptions.compress_threshold,
    error_handler: @@redis_store_error_handler,
    expires_in: RedisMemo::DefaultOptions.expires_in,
    redis: redis,
  )
end

.with_local_cacheObject



76
77
78
79
80
81
82
83
# File 'lib/redis_memo/cache.rb', line 76

def with_local_cache
  RedisMemo::ThreadLocalVar.local_cache = {}
  RedisMemo::ThreadLocalVar.local_dependency_cache = {}
  yield
ensure
  RedisMemo::ThreadLocalVar.local_cache = nil
  RedisMemo::ThreadLocalVar.local_dependency_cache = nil
end

.write(key, value, disable_async: false, raise_error: false, **options) ⇒ Object



107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/redis_memo/cache.rb', line 107

def write(key, value, disable_async: false, raise_error: false, **options)
  RedisMemo::ThreadLocalVar.raise_error = raise_error

  if local_cache
    local_cache[key] = value
  end

  async = RedisMemo::DefaultOptions.async
  if async.nil? || disable_async
    redis_store.write(key, value, **options)
  else
    async.call do
      RedisMemo::ThreadLocalVar.raise_error = raise_error
      redis_store.write(key, value, **options)
    end
  end
end