Chore: Refactor round robin logic (#1015)
Co-authored-by: Pranav Raj S <pranav@thoughtwoot.com>
This commit is contained in:
co-authored by
Pranav Raj S
parent
49db9c5d8a
commit
0fc0dc1683
@@ -188,7 +188,7 @@ class Conversation < ApplicationRecord
|
||||
return unless conversation_status_changed_to_open?
|
||||
return unless should_round_robin?
|
||||
|
||||
inbox.next_available_agent.then { |new_assignee| update_assignee(new_assignee) }
|
||||
::RoundRobin::AssignmentService.new(conversation: self).perform
|
||||
end
|
||||
|
||||
def create_status_change_message(user_name)
|
||||
|
||||
+1
-10
@@ -64,11 +64,6 @@ class Inbox < ApplicationRecord
|
||||
channel.class.name.to_s == 'Channel::WebWidget'
|
||||
end
|
||||
|
||||
def next_available_agent
|
||||
user_id = Redis::Alfred.rpoplpush(round_robin_key, round_robin_key)
|
||||
account.users.find_by(id: user_id)
|
||||
end
|
||||
|
||||
def webhook_data
|
||||
{
|
||||
id: id,
|
||||
@@ -79,10 +74,6 @@ class Inbox < ApplicationRecord
|
||||
private
|
||||
|
||||
def delete_round_robin_agents
|
||||
Redis::Alfred.delete(round_robin_key)
|
||||
end
|
||||
|
||||
def round_robin_key
|
||||
format(Constants::RedisKeys::ROUND_ROBIN_AGENTS, inbox_id: id)
|
||||
::RoundRobin::ManageService.new(inbox: self).clear_queue
|
||||
end
|
||||
end
|
||||
|
||||
@@ -26,14 +26,10 @@ class InboxMember < ApplicationRecord
|
||||
private
|
||||
|
||||
def add_agent_to_round_robin
|
||||
Redis::Alfred.lpush(round_robin_key, user_id)
|
||||
::RoundRobin::ManageService.new(inbox: inbox).add_agent_to_queue(user_id)
|
||||
end
|
||||
|
||||
def remove_agent_from_round_robin
|
||||
Redis::Alfred.lrem(round_robin_key, user_id)
|
||||
end
|
||||
|
||||
def round_robin_key
|
||||
format(Constants::RedisKeys::ROUND_ROBIN_AGENTS, inbox_id: inbox_id)
|
||||
::RoundRobin::ManageService.new(inbox: inbox).remove_agent_from_queue(user_id)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -153,7 +153,6 @@ class Message < ApplicationRecord
|
||||
end
|
||||
|
||||
def notify_via_mail
|
||||
conversation_mail_key = Redis::Alfred::CONVERSATION_MAILER_KEY % conversation.id
|
||||
if Redis::Alfred.get(conversation_mail_key).nil? && conversation.contact.email? && outgoing?
|
||||
# set a redis key for the conversation so that we don't need to send email for every
|
||||
# new message that comes in and we dont enque the delayed sidekiq job for every message
|
||||
@@ -165,6 +164,10 @@ class Message < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def conversation_mail_key
|
||||
format(::Redis::Alfred::CONVERSATION_MAILER_KEY, conversation_id: conversation.id)
|
||||
end
|
||||
|
||||
def validate_attachments_limit(_attachment)
|
||||
errors.add(attachments: 'exceeded maximum allowed') if attachments.size >= NUMBER_OF_PERMITTED_ATTACHMENTS
|
||||
end
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
class RoundRobin::AssignmentService
|
||||
pattr_initialize [:conversation]
|
||||
|
||||
def perform
|
||||
# online agents will get priority
|
||||
new_assignee = round_robin_manage_service.available_agent(priority_list: online_agents)
|
||||
conversation.update(assignee: new_assignee) if new_assignee
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def online_agents
|
||||
online_agents = OnlineStatusTracker.get_available_users(conversation.account_id)
|
||||
online_agents.select { |_key, value| value.eql?('online') }.keys if online_agents.present?
|
||||
end
|
||||
|
||||
def round_robin_manage_service
|
||||
@round_robin_manage_service ||= RoundRobin::ManageService.new(inbox: conversation.inbox)
|
||||
end
|
||||
|
||||
def round_robin_key
|
||||
format(::Redis::Alfred::ROUND_ROBIN_AGENTS, inbox_id: conversation.inbox_id)
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,56 @@
|
||||
class RoundRobin::ManageService
|
||||
pattr_initialize [:inbox!]
|
||||
|
||||
# called on inbox delete
|
||||
def clear_queue
|
||||
::Redis::Alfred.delete(round_robin_key)
|
||||
end
|
||||
|
||||
# called on inbox member create
|
||||
def add_agent_to_queue(user_id)
|
||||
::Redis::Alfred.lpush(round_robin_key, user_id)
|
||||
end
|
||||
|
||||
# called on inbox member delete
|
||||
def remove_agent_from_queue(user_id)
|
||||
::Redis::Alfred.lrem(round_robin_key, user_id)
|
||||
end
|
||||
|
||||
def available_agent(priority_list: [])
|
||||
reset_queue unless validate_queue?
|
||||
user_id = get_agent_via_priority_list(priority_list)
|
||||
# incase priority list was empty or inbox members weren't present
|
||||
user_id ||= ::Redis::Alfred.rpoplpush(round_robin_key, round_robin_key)
|
||||
inbox.inbox_members.find_by(user_id: user_id)&.user if user_id.present?
|
||||
end
|
||||
|
||||
def reset_queue
|
||||
clear_queue
|
||||
add_agent_to_queue(inbox.inbox_members.map(&:user_id))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def get_agent_via_priority_list(priority_list)
|
||||
return if priority_list.blank?
|
||||
|
||||
user_id = queue.intersection(priority_list.map(&:to_s)).pop
|
||||
if user_id.present?
|
||||
remove_agent_from_queue(user_id)
|
||||
add_agent_to_queue(user_id)
|
||||
end
|
||||
user_id
|
||||
end
|
||||
|
||||
def validate_queue?
|
||||
return true if inbox.inbox_members.map(&:user_id).sort == queue.sort.map(&:to_i)
|
||||
end
|
||||
|
||||
def queue
|
||||
::Redis::Alfred.lrange(round_robin_key)
|
||||
end
|
||||
|
||||
def round_robin_key
|
||||
format(::Redis::Alfred::ROUND_ROBIN_AGENTS, inbox_id: inbox.id)
|
||||
end
|
||||
end
|
||||
@@ -9,7 +9,12 @@ class ConversationReplyEmailWorker
|
||||
ConversationReplyMailer.reply_with_summary(@conversation, queued_time).deliver_later
|
||||
|
||||
# delete the redis set from the first new message on the conversation
|
||||
conversation_mail_key = Redis::Alfred::CONVERSATION_MAILER_KEY % @conversation.id
|
||||
Redis::Alfred.delete(conversation_mail_key)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def conversation_mail_key
|
||||
format(::Redis::Alfred::CONVERSATION_MAILER_KEY, conversation_id: @conversation.id)
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user