Feature: Availability Statuses (#874)

Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
This commit is contained in:
Sojan Jose
2020-07-04 11:42:47 +05:30
committed by GitHub
parent bd87927576
commit c98907db49
35 changed files with 413 additions and 77 deletions

View File

@@ -1,19 +1,50 @@
module OnlineStatusTracker
def self.add_subscription(channel_id)
count = subscription_count(channel_id)
::Redis::Alfred.setex(channel_id, count + 1)
PRESENCE_DURATION = 60.seconds
# presence : sorted set with timestamp as the score & object id as value
# obj_type: Contact | User
def self.update_presence(account_id, obj_type, obj_id)
::Redis::Alfred.zadd(presence_key(account_id, obj_type), Time.now.to_i, obj_id)
end
def self.remove_subscription(channel_id)
count = subscription_count(channel_id)
if count == 1
::Redis::Alfred.delete(channel_id)
elsif count != 0
::Redis::Alfred.setex(channel_id, count - 1)
def self.get_presence(account_id, obj_type, obj_id)
connected_time = ::Redis::Alfred.zscore(presence_key(account_id, obj_type), obj_id)
connected_time && connected_time > (Time.zone.now - PRESENCE_DURATION).to_i
end
def self.presence_key(account_id, type)
case type
when 'Contact'
Redis::Alfred::ONLINE_PRESENCE_CONTACTS % account_id
else
Redis::Alfred::ONLINE_PRESENCE_USERS % account_id
end
end
def self.subscription_count(channel_id)
::Redis::Alfred.get(channel_id).to_i
# online status : online | busy | offline
# redis hash with obj_id key && status as value
def self.set_status(account_id, user_id, status)
::Redis::Alfred.hset(status_key(account_id), user_id, status)
end
def self.get_status(account_id, user_id)
::Redis::Alfred.hget(status_key(account_id), user_id)
end
def self.status_key(account_id)
Redis::Alfred::ONLINE_STATUS % account_id
end
def self.get_available_contacts(account_id)
contact_ids = ::Redis::Alfred.zrangebyscore(presence_key(account_id, 'Contact'), (Time.zone.now - PRESENCE_DURATION).to_i, Time.now.to_i)
contact_ids.index_with { |_id| 'online' }
end
def self.get_available_users(account_id)
user_ids = ::Redis::Alfred.zrangebyscore(presence_key(account_id, 'User'), (Time.zone.now - PRESENCE_DURATION).to_i, Time.now.to_i)
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
end
end

View File

@@ -1,6 +1,13 @@
module Redis::Alfred
CONVERSATION_MAILER_KEY = 'CONVERSATION::%d'.freeze
# hash containing user_id key and status as value ONLINE_STATUS::%accountid
ONLINE_STATUS = 'ONLINE_STATUS::%s'.freeze
# sorted set storing online presense of account contacts : ONLINE_PRESENCE::%accountid::CONTACTS
ONLINE_PRESENCE_CONTACTS = 'ONLINE_PRESENCE::%s::CONTACTS'.freeze
# sorted set storing online presense of account users : ONLINE_PRESENCE::%accountid::USERS
ONLINE_PRESENCE_USERS = 'ONLINE_PRESENCE::%s::USERS'.freeze
class << self
def rpoplpush(source, destination)
$alfred.rpoplpush(source, destination)
@@ -22,8 +29,46 @@ module Redis::Alfred
$alfred.setex(key, expiry, value)
end
def set(key, value)
$alfred.set(key, value)
end
def get(key)
$alfred.get(key)
end
# hash operation
# add a key value to redis hash
def hset(key, field, value)
$alfred.hset(key, field, value)
end
# get value from redis hash
def hget(key, field)
$alfred.hget(key, field)
end
# get values of multiple keys from redis hash
def hmget(key, fields)
$alfred.hmget(key, *fields)
end
# sorted set functions
# add score and value for a key
def zadd(key, score, value)
$alfred.zadd(key, score, value)
end
# get score of a value for key
def zscore(key, value)
$alfred.zscore(key, value)
end
# get values by score
def zrangebyscore(key, range_start, range_end)
$alfred.zrangebyscore(key, range_start, range_end)
end
end
end