From e95680e80057f4e06d9f8b2b0a54fe5f10c0e34c Mon Sep 17 00:00:00 2001 From: Vishnu Narayanan Date: Mon, 2 Dec 2024 15:47:54 +0530 Subject: [PATCH] feat: remove stale ONLINE_PRESENCE contact keys in redis (#9558) 50% of Redis memory size comes from ONLINE_PRESENCE keys. This PR adds a periodic job to remove stale keys from all accounts. --- app/jobs/internal/process_stale_redis_keys_job.rb | 11 +++++++++++ app/jobs/internal/remove_stale_redis_keys_job.rb | 14 ++++++++++++++ .../internal/remove_stale_redis_keys_service.rb | 10 ++++++++++ config/schedule.yml | 7 +++++++ 4 files changed, 42 insertions(+) create mode 100644 app/jobs/internal/process_stale_redis_keys_job.rb create mode 100644 app/jobs/internal/remove_stale_redis_keys_job.rb create mode 100644 app/services/internal/remove_stale_redis_keys_service.rb diff --git a/app/jobs/internal/process_stale_redis_keys_job.rb b/app/jobs/internal/process_stale_redis_keys_job.rb new file mode 100644 index 000000000..3afb3b434 --- /dev/null +++ b/app/jobs/internal/process_stale_redis_keys_job.rb @@ -0,0 +1,11 @@ +# housekeeping +# remove contact inboxes that does not have any conversations +# and are older than 3 months + +class Internal::ProcessStaleRedisKeysJob < ApplicationJob + queue_as :low + + def perform(account) + Internal::RemoveStaleRedisKeysService.new(account_id: account.id).perform + end +end diff --git a/app/jobs/internal/remove_stale_redis_keys_job.rb b/app/jobs/internal/remove_stale_redis_keys_job.rb new file mode 100644 index 000000000..667fa398b --- /dev/null +++ b/app/jobs/internal/remove_stale_redis_keys_job.rb @@ -0,0 +1,14 @@ +# housekeeping +# ensure stale ONLINE PRESENCE KEYS for contacts are removed periodically +# should result in 50% redis mem size reduction + +class Internal::RemoveStaleRedisKeysJob < ApplicationJob + queue_as :scheduled_jobs + + def perform + Account.find_each do |account| + Rails.logger.info "Enqueuing ProcessStaleRedisKeysJob for account #{account.id}" + Internal::ProcessStaleRedisKeysJob.perform_later(account) + end + end +end diff --git a/app/services/internal/remove_stale_redis_keys_service.rb b/app/services/internal/remove_stale_redis_keys_service.rb new file mode 100644 index 000000000..a3e1da207 --- /dev/null +++ b/app/services/internal/remove_stale_redis_keys_service.rb @@ -0,0 +1,10 @@ +class Internal::RemoveStaleRedisKeysService + pattr_initialize [:account_id!] + + def perform(account_id) + range_start = (Time.zone.now - PRESENCE_DURATION).to_i + # exclusive minimum score is specified by prefixing ( + # we are clearing old records because this could clogg up the sorted set + ::Redis::Alfred.zremrangebyscore(presence_key(account_id, 'Contact'), '-inf', "(#{range_start}") + end +end diff --git a/config/schedule.yml b/config/schedule.yml index 7a0d2faeb..a92960db8 100644 --- a/config/schedule.yml +++ b/config/schedule.yml @@ -26,3 +26,10 @@ remove_stale_contact_inboxes_job.rb: cron: '30 22 * * *' class: 'Internal::RemoveStaleContactInboxesJob' queue: scheduled_jobs + +# executed daily at 2230 UTC +# which is our lowest traffic time +remove_stale_redis_keys_job.rb: + cron: '30 22 * * *' + class: 'Internal::RemoveStaleRedisKeysJob' + queue: scheduled_jobs