Class: BetterService::CacheService
- Inherits:
-
Object
- Object
- BetterService::CacheService
- Defined in:
- lib/better_service/cache_service.rb
Overview
CacheService - Provides cache invalidation and management for BetterService
This service handles cache invalidation based on contexts defined in the Cacheable concern. It provides methods to invalidate cache keys for specific users, contexts, or globally.
Supports cascading invalidation through INVALIDATION_MAP - when a context is invalidated, all related contexts are also invalidated automatically.
Defined Under Namespace
Classes: CacheInvalidationJob
Class Attribute Summary collapse
-
.invalidation_map ⇒ Hash<String, Array<String>>
readonly
Get the current invalidation map.
Class Method Summary collapse
-
.add_invalidation_rules(entries) ⇒ void
Add entries to the invalidation map without replacing existing ones.
-
.clear_all ⇒ Integer
Clear all BetterService cache.
-
.configure_invalidation_map(map) ⇒ void
Configure the invalidation map for cascading cache invalidation.
-
.contexts_to_invalidate(context) ⇒ Array<String>
Get all contexts that should be invalidated for a given context.
-
.exist?(key) ⇒ Boolean
Check if a key exists in cache.
-
.fetch(key, options = {}, &block) ⇒ Object
Fetch from cache with block.
-
.invalidate_for_context(user, context, async: false, cascade: true) ⇒ Integer
Invalidate cache for a specific context and user.
-
.invalidate_for_user(user, async: false) ⇒ Integer
Invalidate all cache for a specific user.
-
.invalidate_global(context, async: false, cascade: true) ⇒ Integer
Invalidate cache globally for a context.
-
.invalidate_key(key) ⇒ Boolean
Invalidate specific cache key.
-
.stats ⇒ Hash
Get cache statistics.
Class Attribute Details
.invalidation_map ⇒ Hash<String, Array<String>> (readonly)
Get the current invalidation map
38 39 40 |
# File 'lib/better_service/cache_service.rb', line 38 def invalidation_map @invalidation_map end |
Class Method Details
.add_invalidation_rules(entries) ⇒ void
This method returns an undefined value.
Add entries to the invalidation map without replacing existing ones
72 73 74 75 76 77 |
# File 'lib/better_service/cache_service.rb', line 72 def add_invalidation_rules(entries) new_entries = entries.transform_keys(&:to_s).transform_values do |contexts| Array(contexts).map(&:to_s) end @invalidation_map = (@invalidation_map || {}).merge(new_entries).freeze end |
.clear_all ⇒ Integer
Clear all BetterService cache
WARNING: This deletes ALL cache keys that match BetterService patterns. Use with caution, preferably only in development/testing.
242 243 244 245 246 247 |
# File 'lib/better_service/cache_service.rb', line 242 def clear_all pattern = "*:user_*:*" # Match all BetterService cache keys result = delete_matched(pattern) # Ensure we return Integer, not Array result.is_a?(Array) ? result.size : (result || 0) end |
.configure_invalidation_map(map) ⇒ void
This method returns an undefined value.
Configure the invalidation map for cascading cache invalidation
The invalidation map defines which cache contexts should be invalidated together. When a primary context is invalidated, all related contexts in the map are also invalidated.
57 58 59 60 61 |
# File 'lib/better_service/cache_service.rb', line 57 def configure_invalidation_map(map) @invalidation_map = map.transform_keys(&:to_s).transform_values do |contexts| Array(contexts).map(&:to_s) end.freeze end |
.contexts_to_invalidate(context) ⇒ Array<String>
Get all contexts that should be invalidated for a given context
If the context exists in the invalidation map, returns all mapped contexts. Otherwise, returns an array containing just the original context.
90 91 92 93 |
# File 'lib/better_service/cache_service.rb', line 90 def contexts_to_invalidate(context) context_str = context.to_s (@invalidation_map || {})[context_str] || [ context_str ] end |
.exist?(key) ⇒ Boolean
Check if a key exists in cache
273 274 275 276 277 |
# File 'lib/better_service/cache_service.rb', line 273 def exist?(key) return false unless key && !key.to_s.strip.empty? Rails.cache.exist?(key) end |
.fetch(key, options = {}, &block) ⇒ Object
Fetch from cache with block
Wrapper around Rails.cache.fetch with BetterService conventions. If the key exists, returns cached value. Otherwise, executes block, caches the result, and returns it.
265 266 267 |
# File 'lib/better_service/cache_service.rb', line 265 def fetch(key, = {}, &block) Rails.cache.fetch(key, , &block) end |
.invalidate_for_context(user, context, async: false, cascade: true) ⇒ Integer
Invalidate cache for a specific context and user
Deletes all cache keys that match the pattern for the given user and context. Uses cascading invalidation - if the context exists in the invalidation map, all related contexts will also be invalidated.
This is useful when data changes that affects a specific user’s cached results.
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/better_service/cache_service.rb', line 120 def invalidate_for_context(user, context, async: false, cascade: true) return 0 unless user && context && !context.to_s.strip.empty? # Get all contexts to invalidate (cascading or single) contexts = cascade ? contexts_to_invalidate(context) : [ context.to_s ] total_deleted = 0 contexts.each do |ctx| pattern = build_user_context_pattern(user, ctx) if async invalidate_async(pattern) else result = delete_matched(pattern) count = result.is_a?(Array) ? result.size : (result || 0) total_deleted += count end end log_cascading_invalidation(context, contexts) if cascade && contexts.size > 1 total_deleted end |
.invalidate_for_user(user, async: false) ⇒ Integer
Invalidate all cache for a specific user
Deletes all cache keys associated with the given user. This is useful when a user logs out or their permissions change.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/better_service/cache_service.rb', line 198 def invalidate_for_user(user, async: false) return 0 unless user pattern = build_user_pattern(user) if async invalidate_async(pattern) 0 else result = delete_matched(pattern) # Ensure we return Integer, not Array result.is_a?(Array) ? result.size : (result || 0) end end |
.invalidate_global(context, async: false, cascade: true) ⇒ Integer
Invalidate cache globally for a context
Deletes all cache keys for the given context across all users. Uses cascading invalidation - if the context exists in the invalidation map, all related contexts will also be invalidated.
This is useful when data changes that affects everyone (e.g., global settings).
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/better_service/cache_service.rb', line 163 def invalidate_global(context, async: false, cascade: true) return 0 unless context && !context.to_s.strip.empty? # Get all contexts to invalidate (cascading or single) contexts = cascade ? contexts_to_invalidate(context) : [ context.to_s ] total_deleted = 0 contexts.each do |ctx| pattern = build_global_context_pattern(ctx) if async invalidate_async(pattern) else result = delete_matched(pattern) count = result.is_a?(Array) ? result.size : (result || 0) total_deleted += count end end log_cascading_invalidation(context, contexts, global: true) if cascade && contexts.size > 1 total_deleted end |
.invalidate_key(key) ⇒ Boolean
Invalidate specific cache key
Deletes a single cache key. Useful when you know the exact key.
222 223 224 225 226 227 228 229 230 |
# File 'lib/better_service/cache_service.rb', line 222 def invalidate_key(key) return false unless key && !key.to_s.strip.empty? Rails.cache.delete(key) true rescue ArgumentError # Rails.cache.delete raises ArgumentError for invalid keys false end |
.stats ⇒ Hash
Get cache statistics
Returns information about cache store and BetterService cache usage. Note: Detailed stats only available with certain cache stores (Redis).
285 286 287 288 289 290 291 292 293 |
# File 'lib/better_service/cache_service.rb', line 285 def stats { cache_store: Rails.cache.class.name, supports_pattern_deletion: supports_delete_matched?, supports_async: defined?(ActiveJob) ? true : false, invalidation_map_configured: (@invalidation_map || {}).any?, invalidation_map_contexts: (@invalidation_map || {}).keys } end |