From a2d0e60a8822b0f49de9c0b6549a316299d44032 Mon Sep 17 00:00:00 2001 From: Sojan Jose Date: Wed, 15 May 2024 21:23:19 -0700 Subject: [PATCH] fix: Get online status from db when not present in cache [CW-3233] (#9477) Previously, we returned the static value 'online' when the status was not present in the Redis cache. This PR changes it to fall back to the DB value and updates the cache in such cases. fixes: https://linear.app/chatwoot/issue/CW-3233/write-a-back-up-for-online-status-in-case-if-redis-keys-are-not --- lib/online_status_tracker.rb | 8 +++++++- spec/lib/online_status_tracker_spec.rb | 14 +++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/online_status_tracker.rb b/lib/online_status_tracker.rb index 40ec7071b..bc2ed1dbc 100644 --- a/lib/online_status_tracker.rb +++ b/lib/online_status_tracker.rb @@ -57,7 +57,13 @@ class OnlineStatusTracker return {} if user_ids.blank? user_availabilities = ::Redis::Alfred.hmget(status_key(account_id), user_ids) - user_ids.map.with_index { |id, index| [id, (user_availabilities[index] || 'online')] }.to_h + user_ids.map.with_index { |id, index| [id, (user_availabilities[index] || get_availability_from_db(account_id, id))] }.to_h + end + + def self.get_availability_from_db(account_id, user_id) + availability = Account.find(account_id).account_users.find_by(user_id: user_id).availability + set_status(account_id, user_id, availability) + availability end def self.get_available_user_ids(account_id) diff --git a/spec/lib/online_status_tracker_spec.rb b/spec/lib/online_status_tracker_spec.rb index c2f69ffac..d88298485 100644 --- a/spec/lib/online_status_tracker_spec.rb +++ b/spec/lib/online_status_tracker_spec.rb @@ -9,10 +9,11 @@ describe OnlineStatusTracker do context 'when get_available_users' do before do described_class.update_presence(account.id, 'User', user1.id) + described_class.update_presence(account.id, 'User', user2.id) end it 'returns only the online user ids with presence' do - expect(described_class.get_available_users(account.id).keys).to contain_exactly(user1.id.to_s) + expect(described_class.get_available_users(account.id).keys).to contain_exactly(user1.id.to_s, user2.id.to_s) expect(described_class.get_available_users(account.id).values).not_to include(user3.id) end @@ -20,6 +21,17 @@ describe OnlineStatusTracker do user2.account_users.first.update(auto_offline: false) expect(described_class.get_available_users(account.id).keys).to contain_exactly(user1.id.to_s, user2.id.to_s) end + + it 'returns the availability from the db if it is not present in redis and set it in redis' do + user2.account_users.find_by(account_id: account.id).update!(availability: 'offline') + # clear the redis cache to ensure values are fetched from db + Redis::Alfred.delete(format(Redis::Alfred::ONLINE_STATUS, account_id: account.id)) + expect(described_class.get_available_users(account.id)[user1.id.to_s]).to eq('online') + expect(described_class.get_available_users(account.id)[user2.id.to_s]).to eq('offline') + # ensure online status is also set + expect(Redis::Alfred.hmget(format(Redis::Alfred::ONLINE_STATUS, account_id: account.id), + [user1.id.to_s, user2.id.to_s])).to eq(%w[online offline]) + end end context 'when get_available_contacts' do