Module: IdentityCache

Extended by:
ActiveSupport::Concern, CacheHash
Includes:
WithPrimaryIndex
Defined in:
lib/identity_cache.rb,
lib/identity_cache/cached.rb,
lib/identity_cache/encoder.rb,
lib/identity_cache/railtie.rb,
lib/identity_cache/version.rb,
lib/identity_cache/query_api.rb,
lib/identity_cache/cache_hash.rb,
lib/identity_cache/expiry_hook.rb,
lib/identity_cache/cache_fetcher.rb,
lib/identity_cache/cache_key_loader.rb,
lib/identity_cache/cached/attribute.rb,
lib/identity_cache/fallback_fetcher.rb,
lib/identity_cache/record_not_found.rb,
lib/identity_cache/should_use_cache.rb,
lib/identity_cache/cached/belongs_to.rb,
lib/identity_cache/cached/prefetcher.rb,
lib/identity_cache/configuration_dsl.rb,
lib/identity_cache/belongs_to_caching.rb,
lib/identity_cache/cache_invalidation.rb,
lib/identity_cache/cached/association.rb,
lib/identity_cache/load_strategy/lazy.rb,
lib/identity_cache/with_primary_index.rb,
lib/identity_cache/load_strategy/eager.rb,
lib/identity_cache/mem_cache_store_cas.rb,
lib/identity_cache/cache_key_generation.rb,
lib/identity_cache/cached/primary_index.rb,
lib/identity_cache/memoized_cache_proxy.rb,
lib/identity_cache/without_primary_index.rb,
lib/identity_cache/cached/attribute_by_one.rb,
lib/identity_cache/parent_model_expiration.rb,
lib/identity_cache/cached/embedded_fetching.rb,
lib/identity_cache/cached/recursive/has_one.rb,
lib/identity_cache/cached/reference/has_one.rb,
lib/identity_cache/cached/attribute_by_multi.rb,
lib/identity_cache/cached/recursive/has_many.rb,
lib/identity_cache/cached/reference/has_many.rb,
lib/identity_cache/load_strategy/load_request.rb,
lib/identity_cache/cached/recursive/association.rb,
lib/identity_cache/cached/reference/association.rb,
lib/identity_cache/load_strategy/multi_load_request.rb

Defined Under Namespace

Modules: BelongsToCaching, CacheHash, CacheInvalidation, CacheKeyGeneration, ConfigurationDSL, LoadStrategy, MemCacheStoreCAS, QueryAPI, ShouldUseCache, WithPrimaryIndex, WithoutPrimaryIndex Classes: AlreadyIncludedError, AssociationError, CacheFetcher, DerivedModelError, FallbackFetcher, InverseAssociationError, LockWaitTimeout, MemoizedCacheProxy, NestedDeferredParentBlockError, Railtie, RecordNotFound, UnsupportedAssociationError, UnsupportedScopeError

Constant Summary collapse

CACHED_NIL =
:idc_cached_nil
BATCH_SIZE =
1000
DELETED =
:idc_cached_deleted
DELETED_TTL =
1000
VERSION =
"1.6.1"
CACHE_VERSION =
8

Constants included from CacheInvalidation

CacheInvalidation::CACHE_KEY_NAMES

Constants included from CacheKeyGeneration

CacheKeyGeneration::DEFAULT_NAMESPACE

Class Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from CacheHash

memcache_hash

Methods included from WithPrimaryIndex

#expire_cache, #expire_primary_index, #primary_cache_index_key

Methods included from CacheInvalidation

#reload

Methods included from QueryAPI

#_run_commit_callbacks, #expire_cache, #was_new_record?

Methods included from CacheKeyGeneration

denormalized_schema_hash, denormalized_schema_string, schema_to_string

Class Attribute Details

.fetch_read_only_recordsObject



251
252
253
254
255
256
# File 'lib/identity_cache.rb', line 251

def fetch_read_only_records
  v = Thread.current[:identity_cache_fetch_read_only_records]
  return v unless v.nil?

  @fetch_read_only_records
end

.loggerObject



112
113
114
# File 'lib/identity_cache.rb', line 112

def logger
  @logger || Rails.logger
end

.readonlyObject

Returns the value of attribute readonly.



85
86
87
# File 'lib/identity_cache.rb', line 85

def readonly
  @readonly
end

Class Method Details

.append_features(base) ⇒ Object

:nodoc:



88
89
90
91
92
# File 'lib/identity_cache.rb', line 88

def append_features(base) # :nodoc:
  raise AlreadyIncludedError if base.include?(IdentityCache)

  super
end

.cacheObject



108
109
110
# File 'lib/identity_cache.rb', line 108

def cache
  @cache ||= MemoizedCacheProxy.new
end

.cache_backend=(cache_adaptor) ⇒ Object

Sets the cache adaptor IdentityCache will be using

Parameters

cache_adaptor - A ActiveSupport::Cache::Store



100
101
102
103
104
105
106
# File 'lib/identity_cache.rb', line 100

def cache_backend=(cache_adaptor)
  if defined?(@cache)
    cache.cache_backend = cache_adaptor
  else
    @cache = MemoizedCacheProxy.new(cache_adaptor)
  end
end

.eager_load!Object



258
259
260
# File 'lib/identity_cache.rb', line 258

def eager_load!
  ParentModelExpiration.install_all_pending_parent_expiry_hooks
end

.fetch(key, cache_fetcher_options = {}) ⇒ Object

Cache retrieval and miss resolver primitive; given a key it will try to retrieve the associated value from the cache otherwise it will return the value of the execution of the block.

Parameters

key A cache key string cache_fetcher_options A hash of options to pass to the cache backend



161
162
163
164
165
166
167
168
169
# File 'lib/identity_cache.rb', line 161

def fetch(key, cache_fetcher_options = {})
  if should_use_cache?
    unmap_cached_nil_for(cache.fetch(key, cache_fetcher_options) do
      map_cached_nil_for(yield)
    end)
  else
    yield
  end
end

.fetch_multi(*keys) ⇒ Object

Same as fetch, except that it will try a collection of keys, using the multiget operation of the cache adaptor.

Parameters

keys A collection or array of key strings



184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
# File 'lib/identity_cache.rb', line 184

def fetch_multi(*keys)
  keys.flatten!(1)
  return {} if keys.empty?

  result = if should_use_cache?
    fetch_in_batches(keys.uniq) do |missed_keys|
      results = yield missed_keys
      results.map { |e| map_cached_nil_for(e) }
    end
  else
    results = yield keys
    Hash[keys.zip(results)]
  end

  result.each do |key, value|
    result[key] = unmap_cached_nil_for(value)
  end

  result
end

.map_cached_nil_for(value) ⇒ Object



171
172
173
# File 'lib/identity_cache.rb', line 171

def map_cached_nil_for(value)
  value.nil? ? IdentityCache::CACHED_NIL : value
end

.should_fill_cache?Boolean

:nodoc:

Returns:

  • (Boolean)


116
117
118
# File 'lib/identity_cache.rb', line 116

def should_fill_cache? # :nodoc:
  !readonly
end

.unmap_cached_nil_for(value) ⇒ Object



175
176
177
# File 'lib/identity_cache.rb', line 175

def unmap_cached_nil_for(value)
  value == IdentityCache::CACHED_NIL ? nil : value
end

.with_deferred_parent_expirationObject

Executes a block with deferred parent expiration, ensuring that the parent records’ cache expiration is deferred until the block completes. When the block completes, it triggers expiration of the primary index for the parent records. Raises a NestedDeferredParentBlockError if a deferred parent expiration block is already active on the current thread.

Parameters:

No parameters.

Raises:

NestedDeferredParentBlockError if a deferred parent expiration block is already active.

Yield:

Runs the provided block with deferred parent expiration.

Returns:

The result of executing the provided block.

Ensures:

Cleans up thread-local variables related to deferred parent expiration regardless of whether the block raises an exception.



226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
# File 'lib/identity_cache.rb', line 226

def with_deferred_parent_expiration
  raise NestedDeferredParentBlockError if Thread.current[:idc_deferred_parent_expiration]

  Thread.current[:idc_deferred_parent_expiration] = true
  Thread.current[:idc_parent_records_for_cache_expiry] = Set.new

  result = yield

  Thread.current[:idc_deferred_parent_expiration] = nil
  Thread.current[:idc_parent_records_for_cache_expiry].each(&:expire_primary_index)

  result
ensure
  Thread.current[:idc_deferred_parent_expiration] = nil
  Thread.current[:idc_parent_records_for_cache_expiry].clear
end

.with_fetch_read_only_records(value = true) ⇒ Object



243
244
245
246
247
248
249
# File 'lib/identity_cache.rb', line 243

def with_fetch_read_only_records(value = true)
  old_value = Thread.current[:identity_cache_fetch_read_only_records]
  Thread.current[:identity_cache_fetch_read_only_records] = value
  yield
ensure
  Thread.current[:identity_cache_fetch_read_only_records] = old_value
end

Instance Method Details

#should_use_cache?Boolean

:nodoc:

Returns:

  • (Boolean)


138
139
140
141
142
143
# File 'lib/identity_cache.rb', line 138

def should_use_cache? # :nodoc:
  ActiveRecord::Base.connection_handler.connection_pool_list(ActiveRecord::Base.current_role).none? do |pool|
    pool.active_connection? &&
      pool.active_connection.current_transaction.joinable?
  end
end