Class: ScheduleWorkers::AvailableTimesCacheCleaner
- Inherits:
-
ApplicationWorker
- Object
- ApplicationWorker
- ScheduleWorkers::AvailableTimesCacheCleaner
- Includes:
- ElasticAPM::SpanHelpers
- Defined in:
- app/workers/schedule_workers/available_times_cache_cleaner.rb
Overview
ScheduleWorkers::AvailableTimesCacheCleaner This worker is responsible for cleaning up stale available_times cache keys on a scheduled basis. It addresses the memory bloat issue where multiple cache keys accumulate for the same restaurant package or restaurant add-on due to changes in agenda_setting, start_date, end_date, or time_zone.
Problem:
The cache key format includes a hash of variables like [agenda_setting, start_date, end_date].
When these values change, a new cache key is created, but old keys are not deleted.
This leads to Redis memory bloat with multiple stale keys per restaurant package/add-on.
Example of stale keys (for restaurant_package_37267):
available_times_v2_version_v2025-03-08:{restaurant_package_37267}:variables_331924283
available_times_v2_version_v2025-03-08:{restaurant_package_37267}:variables_3977971064
available_times_v2_version_v2025-03-08:{restaurant_package_37267}:variables_2558844315
... (23 keys consuming ~8MB for ONE package)
Solution:
- Keep only ONE key per restaurant_package or restaurant_add_on (the most recently accessed one)
- Delete all other stale keys
Constant Summary collapse
- REDIS_SCAN_COUNT =
Configuration
1000- BATCH_SIZE =
100- CACHE_PATTERNS =
Cache key patterns to clean
[ { pattern: 'available_times_v2_version_*:{restaurant_package_*}:*', id_regex: /:?\{restaurant_package_(\d+)\}:/, type: 'restaurant_package' }, { pattern: 'restaurant-add-on-inv:{restaurant_add_on_*}:*', id_regex: /:?\{restaurant_add_on_(\d+)\}:/, type: 'restaurant_add_on' }, ].freeze
Instance Method Summary collapse
-
#perform ⇒ Object
Main entry point for the worker.
Methods inherited from ApplicationWorker
Instance Method Details
#perform ⇒ Object
Main entry point for the worker
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'app/workers/schedule_workers/available_times_cache_cleaner.rb', line 41 def perform ElasticAPM.with_span('Available Times Cache Cleanup', 'cache', subtype: 'redis', action: 'cleanup') do |_span| cleanup_stats = { restaurant_packages_processed: 0, restaurant_add_ons_processed: 0, stale_keys_deleted: 0, total_memory_freed: 0, errors: 0, } begin HH_LOGGER.info('available_times_cache_cleanup_started', { timestamp: Time.current.iso8601, }) CACHE_PATTERNS.each do |config| # Scan and group keys by entity ID entity_keys = scan_and_group_keys(config[:pattern], config[:id_regex]) HH_LOGGER.info('available_times_cache_scan_completed', { type: config[:type], unique_entities: entity_keys.size, total_keys_found: entity_keys.values.flatten.size, }) # Process each entity entity_keys.each do |entity_id, keys| entity_stats = cleanup_entity_cache(entity_id, keys, config[:type]) if config[:type] == 'restaurant_package' cleanup_stats[:restaurant_packages_processed] += 1 else cleanup_stats[:restaurant_add_ons_processed] += 1 end cleanup_stats[:stale_keys_deleted] += entity_stats[:deleted_count] cleanup_stats[:total_memory_freed] += entity_stats[:memory_freed] rescue StandardError => e cleanup_stats[:errors] += 1 APMErrorHandler.report(e, context: { entity_id: entity_id, type: config[:type] }) end end HH_LOGGER.info('available_times_cache_cleanup_completed', cleanup_stats.merge( memory_freed_mb: (cleanup_stats[:total_memory_freed] / 1024.0 / 1024.0).round(2), )) rescue StandardError => e APMErrorHandler.report(e, context: { cleanup_stats: cleanup_stats }) raise end end end |