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.0"- CACHE_VERSION =
8
Constants included from CacheInvalidation
CacheInvalidation::CACHE_KEY_NAMES
Constants included from CacheKeyGeneration
CacheKeyGeneration::DEFAULT_NAMESPACE
Class Attribute Summary collapse
- .fetch_read_only_records ⇒ Object
- .logger ⇒ Object
-
.readonly ⇒ Object
Returns the value of attribute readonly.
Class Method Summary collapse
-
.append_features(base) ⇒ Object
:nodoc:.
- .cache ⇒ Object
-
.cache_backend=(cache_adaptor) ⇒ Object
Sets the cache adaptor IdentityCache will be using.
- .eager_load! ⇒ Object
-
.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.
-
.fetch_multi(*keys) ⇒ Object
Same as
fetch, except that it will try a collection of keys, using the multiget operation of the cache adaptor. - .map_cached_nil_for(value) ⇒ Object
-
.should_fill_cache? ⇒ Boolean
:nodoc:.
-
.should_use_cache? ⇒ Boolean
:nodoc:.
- .unmap_cached_nil_for(value) ⇒ Object
-
.with_deferred_parent_expiration ⇒ Object
Executes a block with deferred parent expiration, ensuring that the parent records’ cache expiration is deferred until the block completes.
- .with_fetch_read_only_records(value = true) ⇒ Object
Methods included from CacheHash
Methods included from WithPrimaryIndex
#expire_cache, #expire_primary_index, #primary_cache_index_key
Methods included from CacheInvalidation
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_records ⇒ Object
242 243 244 245 246 247 |
# File 'lib/identity_cache.rb', line 242 def fetch_read_only_records v = Thread.current[:identity_cache_fetch_read_only_records] return v unless v.nil? @fetch_read_only_records end |
.logger ⇒ Object
112 113 114 |
# File 'lib/identity_cache.rb', line 112 def logger @logger || Rails.logger end |
.readonly ⇒ Object
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 |
.cache ⇒ Object
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
249 250 251 |
# File 'lib/identity_cache.rb', line 249 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
152 153 154 155 156 157 158 159 160 |
# File 'lib/identity_cache.rb', line 152 def fetch(key, = {}) if should_use_cache? unmap_cached_nil_for(cache.fetch(key, ) 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
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 |
# File 'lib/identity_cache.rb', line 175 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
162 163 164 |
# File 'lib/identity_cache.rb', line 162 def map_cached_nil_for(value) value.nil? ? IdentityCache::CACHED_NIL : value end |
.should_fill_cache? ⇒ Boolean
:nodoc:
116 117 118 |
# File 'lib/identity_cache.rb', line 116 def should_fill_cache? # :nodoc: !readonly end |
.should_use_cache? ⇒ Boolean
:nodoc:
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/identity_cache.rb', line 120 def should_use_cache? # :nodoc: ActiveRecord::Base.connection_handler.connection_pool_list(ActiveRecord::Base.current_role).none? do |pool| pool.active_connection? && # Rails wraps each of your tests in a transaction, so that any changes # made to the database during the test can be rolled back afterwards. # These transactions are flagged as "unjoinable", which tries to make # your application behave as if they weren't there. In particular: # # - Opening another transaction during the test creates a savepoint, # which can be rolled back independently of the main transaction. # - When those nested transactions complete, any `after_commit` # callbacks for records modified during the transaction will run, # even though the changes haven't actually been committed yet. # # By ignoring unjoinable transactions, IdentityCache's behaviour # during your test suite will more closely match production. # # When there are no open transactions, `current_transaction` returns a # special `NullTransaction` object that is unjoinable, meaning we will # use the cache. pool.connection.current_transaction.joinable? end end |
.unmap_cached_nil_for(value) ⇒ Object
166 167 168 |
# File 'lib/identity_cache.rb', line 166 def unmap_cached_nil_for(value) value == IdentityCache::CACHED_NIL ? nil : value end |
.with_deferred_parent_expiration ⇒ Object
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.
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 |
# File 'lib/identity_cache.rb', line 217 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
234 235 236 237 238 239 240 |
# File 'lib/identity_cache.rb', line 234 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 |