# File lib/startback/caching/entity_cache.rb, line 102 def primary_key(candidate_key) candidate_key end
class Startback::Caching::EntityCache
A overriable caching abstraction aiming at making Entity-based caching easy.
This class MUST be overriden:
-
the `load_entity` protected method MUST be implemented to load data from a primary & context unaware key.
-
the `primary_key` protected method MAY be implemented to convert candidate keys (received from ultimate callers) to primary keys. The method is also a good place to check and/or log the keys actually used by callers.
-
the `context_free_key` protected method MAY be overriden to provide domain unrelated caching keys from primary keys, e.g. by encoding the context into the caching key itself, if needed.
-
the `valid?` protected method MAY be overriden to check validity of data extracted from the cache and force a refresh even if found.
An EntityCache
takes an actual store at construction. The object must meet the specification writtern in Store
. The 'cache' ruby gem can be used in practice.
Cache hits, outdated and miss are logged in debug, info, and info severity. The `cache_hit`, `cache_outdated`, `cache_miss` protected methods MAY be overriden to change that behavior.
Attributes
Default time to live, in seconds
Public Class Methods
# File lib/startback/caching/entity_cache.rb, line 37 def default_ttl @default_ttl || (superclass.respond_to?(:default_ttl, true) && superclass.default_ttl) || 3600 end
# File lib/startback/caching/entity_cache.rb, line 43 def initialize(store, context = nil) @store = store @context = context end
Public Instance Methods
Returns the entity corresponding to a given key.
If the entity is not in cache, loads it and puts it in cache using the caching options passed as second parameter.
# File lib/startback/caching/entity_cache.rb, line 53 def get(candidate_key, caching_options = default_caching_options) pkey = primary_key(candidate_key) cache_key = encode_key(context_free_key(pkey)) if store.exist?(cache_key) cached = store.get(cache_key) if valid?(pkey, cached) cache_hit(pkey, cached) return cached else cache_outdated(pkey, cached) end end cache_miss(pkey) load_entity(pkey).tap{|to_cache| store.set(cache_key, to_cache, caching_options) } end
Invalidates the cache under a given key.
# File lib/startback/caching/entity_cache.rb, line 72 def invalidate(candidate_key) pkey = primary_key(candidate_key) cache_key = encode_key(context_free_key(pkey)) store.delete(cache_key) end
Protected Instance Methods
# File lib/startback/caching/entity_cache.rb, line 80 def cache_hit(pkey, cached) log(:debug, self, "cache_hit", context, op_data: pkey) end
# File lib/startback/caching/entity_cache.rb, line 88 def cache_miss(pkey) log(:info, self, "cache_miss", context, op_data: pkey) end
# File lib/startback/caching/entity_cache.rb, line 84 def cache_outdated(pkey, cached) log(:info, self, "cache_outdated", context, op_data: pkey) end
Converts a primary_key
to a context_free_key
, using the context (instance variable) to encode the context itself into the actual cache key.
The default implementation simply returns the primary key and MAY be overriden.
# File lib/startback/caching/entity_cache.rb, line 130 def context_free_key(primary_key) full_key(primary_key) end
# File lib/startback/caching/entity_cache.rb, line 92 def default_caching_options { ttl: self.class.default_ttl } end
Encodes a context free key to an actual cache key.
Default implementation uses JSON.fast_generate but MAY be overriden.
# File lib/startback/caching/entity_cache.rb, line 110 def encode_key(context_free_key) JSON.fast_generate(context_free_key) end
Deprecated, will be removed in 0.6.0. Use context_free_key
instead.
# File lib/startback/caching/entity_cache.rb, line 136 def full_key(primary_key) primary_key end
Actually loads the entity using the given primary key, and possibly the cache context.
This method MUST be implemented and raises a NotImplementedError by default.
# File lib/startback/caching/entity_cache.rb, line 145 def load_entity(primary_key) load_raw_data(primary_key) end
Deprecated, will be removed in 0.6.0. Use load_entity
instead.
# File lib/startback/caching/entity_cache.rb, line 151 def load_raw_data(*args, &bl) raise NotImplementedError, "#{self.class.name}#load_entity" end
Converts a candidate key to a primary key, so as to prevent cache duplicates if callers are allowed to request an entity through various keys.
The default implementation returns the candidate key and MAY be overriden.
Returns whether `cached` entity seems fresh enough to be returned as a cache hit.
This method provides a way to check freshness using, e.g. `updated_at` or `etag` kind of entity fields. The default implementation returns true and MAY be overriden.
# File lib/startback/caching/entity_cache.rb, line 120 def valid?(primary_key, cached) true end