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, Railtie, RecordNotFound, UnsupportedAssociationError, UnsupportedScopeError

Constant Summary collapse

CACHED_NIL =
:idc_cached_nil
BATCH_SIZE =
1000
DELETED =
:idc_cached_deleted
DELETED_TTL =
1000
VERSION =
"1.5.6"
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

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



202
203
204
205
206
207
# File 'lib/identity_cache.rb', line 202

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



110
111
112
# File 'lib/identity_cache.rb', line 110

def logger
  @logger || Rails.logger
end

.readonlyObject

Returns the value of attribute readonly.



83
84
85
# File 'lib/identity_cache.rb', line 83

def readonly
  @readonly
end

Class Method Details

.append_features(base) ⇒ Object

:nodoc:



86
87
88
89
90
# File 'lib/identity_cache.rb', line 86

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

  super
end

.cacheObject



106
107
108
# File 'lib/identity_cache.rb', line 106

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



98
99
100
101
102
103
104
# File 'lib/identity_cache.rb', line 98

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

.eager_load!Object



209
210
211
# File 'lib/identity_cache.rb', line 209

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



150
151
152
153
154
155
156
157
158
# File 'lib/identity_cache.rb', line 150

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



173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
# File 'lib/identity_cache.rb', line 173

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



160
161
162
# File 'lib/identity_cache.rb', line 160

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

.should_fill_cache?Boolean

:nodoc:

Returns:

  • (Boolean)


114
115
116
# File 'lib/identity_cache.rb', line 114

def should_fill_cache? # :nodoc:
  !readonly
end

.should_use_cache?Boolean

:nodoc:

Returns:

  • (Boolean)


118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/identity_cache.rb', line 118

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



164
165
166
# File 'lib/identity_cache.rb', line 164

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

.with_fetch_read_only_records(value = true) ⇒ Object



194
195
196
197
198
199
200
# File 'lib/identity_cache.rb', line 194

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