Files
leadchat/lib/webhooks/trigger.rb
Pranav 8f95fafff4 feat: Add a setting to keep conversations pending on bot failures (#13512)
Adds an account-level setting `keep_pending_on_bot_failure` to control
whether conversations should move from pending to open when agent bot
webhooks fail.

Some users experience occasional message drops and don't want
conversations to automatically reopen due to transient bot failures.
This setting gives accounts control over that behavior. This is a
temporary setting which will be removed in future once a proper fix for
it is done, so it is not added in the UI.
2026-02-10 17:27:42 -08:00

89 lines
2.1 KiB
Ruby

class Webhooks::Trigger
SUPPORTED_ERROR_HANDLE_EVENTS = %w[message_created message_updated].freeze
def initialize(url, payload, webhook_type)
@url = url
@payload = payload
@webhook_type = webhook_type
end
def self.execute(url, payload, webhook_type)
new(url, payload, webhook_type).execute
end
def execute
perform_request
rescue StandardError => e
handle_error(e)
Rails.logger.warn "Exception: Invalid webhook URL #{@url} : #{e.message}"
end
private
def perform_request
RestClient::Request.execute(
method: :post,
url: @url,
payload: @payload.to_json,
headers: { content_type: :json, accept: :json },
timeout: webhook_timeout
)
end
def handle_error(error)
return unless SUPPORTED_ERROR_HANDLE_EVENTS.include?(@payload[:event])
return unless message
case @webhook_type
when :agent_bot_webhook
update_conversation_status(message)
when :api_inbox_webhook
update_message_status(error)
end
end
def update_conversation_status(message)
conversation = message.conversation
return unless conversation&.pending?
return if conversation&.account&.keep_pending_on_bot_failure
conversation.open!
create_agent_bot_error_activity(conversation)
end
def create_agent_bot_error_activity(conversation)
content = I18n.t('conversations.activity.agent_bot.error_moved_to_open')
Conversations::ActivityMessageJob.perform_later(conversation, activity_message_params(conversation, content))
end
def activity_message_params(conversation, content)
{
account_id: conversation.account_id,
inbox_id: conversation.inbox_id,
message_type: :activity,
content: content
}
end
def update_message_status(error)
Messages::StatusUpdateService.new(message, 'failed', error.message).perform
end
def message
return if message_id.blank?
@message ||= Message.find_by(id: message_id)
end
def message_id
@payload[:id]
end
def webhook_timeout
raw_timeout = GlobalConfig.get_value('WEBHOOK_TIMEOUT')
timeout = raw_timeout.presence&.to_i
timeout&.positive? ? timeout : 5
end
end