diff --git a/lib/online_status_tracker.rb b/lib/online_status_tracker.rb index 2dcc102a8..41e384c6b 100644 --- a/lib/online_status_tracker.rb +++ b/lib/online_status_tracker.rb @@ -39,7 +39,11 @@ module OnlineStatusTracker end def self.get_available_contact_ids(account_id) - ::Redis::Alfred.zrangebyscore(presence_key(account_id, 'Contact'), (Time.zone.now - PRESENCE_DURATION).to_i, Time.now.to_i) + 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}") + ::Redis::Alfred.zrangebyscore(presence_key(account_id, 'Contact'), range_start, '+inf') end def self.get_available_contacts(account_id) @@ -58,9 +62,8 @@ module OnlineStatusTracker def self.get_available_user_ids(account_id) account = Account.find(account_id) - # TODO: to migrate this to zrange as its is being deprecated - # https://redis.io/commands/zrangebyscore/ - user_ids = ::Redis::Alfred.zrangebyscore(presence_key(account_id, 'User'), (Time.zone.now - PRESENCE_DURATION).to_i, Time.now.to_i) + range_start = (Time.zone.now - PRESENCE_DURATION).to_i + user_ids = ::Redis::Alfred.zrangebyscore(presence_key(account_id, 'User'), range_start, '+inf') # since we are dealing with redis items as string, casting to string user_ids += account.account_users.where(auto_offline: false)&.map(&:user_id)&.map(&:to_s) user_ids.uniq diff --git a/lib/redis/alfred.rb b/lib/redis/alfred.rb index ca02eb936..fb782a286 100644 --- a/lib/redis/alfred.rb +++ b/lib/redis/alfred.rb @@ -89,5 +89,11 @@ module Redis::Alfred def zrangebyscore(key, range_start, range_end) $alfred.zrangebyscore(key, range_start, range_end) end + + # remove values by score + # exclusive score is specified by prefixing ( + def zremrangebyscore(key, range_start, range_end) + $alfred.zremrangebyscore(key, range_start, range_end) + end end end diff --git a/spec/lib/online_status_tracker_spec.rb b/spec/lib/online_status_tracker_spec.rb index cb7770d42..d4890a6f3 100644 --- a/spec/lib/online_status_tracker_spec.rb +++ b/spec/lib/online_status_tracker_spec.rb @@ -21,4 +21,25 @@ describe OnlineStatusTracker do expect(described_class.get_available_users(account.id).keys).to contain_exactly(user1.id.to_s, user2.id.to_s) end end + + context 'when get_available_contacts' do + let(:online_contact) { create(:contact, account: account) } + let(:offline_contact) { create(:contact, account: account) } + + before do + described_class.update_presence(account.id, 'Contact', online_contact.id) + # creating a stale record for offline contact presence + ::Redis::Alfred.zadd(format(::Redis::Alfred::ONLINE_PRESENCE_CONTACTS, account_id: account.id), + (Time.zone.now - (OnlineStatusTracker::PRESENCE_DURATION + 20)).to_i, offline_contact.id) + end + + it 'returns only the online contact ids with presence' do + expect(described_class.get_available_contacts(account.id).keys).to contain_exactly(online_contact.id.to_s) + end + + it 'flushes the stale records from sorted set after the duration' do + described_class.get_available_contacts(account.id) + expect(::Redis::Alfred.zscore(format(::Redis::Alfred::ONLINE_PRESENCE_CONTACTS, account_id: account.id), offline_contact.id)).to be_nil + end + end end