refactor: move the imap backoff keys to installation configs

This commit is contained in:
Tanmay Deep Sharma
2026-02-26 13:09:49 +05:30
parent 1a158317fb
commit beeb023e19
4 changed files with 30 additions and 9 deletions
+16 -7
View File
@@ -39,8 +39,6 @@ class Channel::Email < ApplicationRecord
include Reauthorizable
AUTHORIZATION_ERROR_THRESHOLD = 10
IMAP_BACKOFF_MAX_INTERVAL_MINUTES = 5
IMAP_BACKOFF_MAX_INTERVAL_COUNT = 5
# TODO: Remove guard once encryption keys become mandatory (target 3-4 releases out).
if Chatwoot.encryption_configured?
@@ -85,17 +83,14 @@ class Channel::Email < ApplicationRecord
def apply_imap_backoff!
new_count = imap_retry_count + 1
max_retries = (IMAP_BACKOFF_MAX_INTERVAL_MINUTES - 1) + IMAP_BACKOFF_MAX_INTERVAL_COUNT
max_retries = imap_backoff_max_retries
if new_count > max_retries
Rails.logger.warn "Error for email channel - #{inbox.id} exhausted backoff (#{new_count} failures), prompting reauthorization"
clear_imap_backoff!
prompt_reauthorization!
else
wait_minutes = [new_count, IMAP_BACKOFF_MAX_INTERVAL_MINUTES].min
::Redis::Alfred.set(imap_retry_count_key, new_count.to_s)
::Redis::Alfred.set(imap_retry_after_key, wait_minutes.minutes.from_now.to_f.to_s)
Rails.logger.warn "Error for email channel - #{inbox.id} backoff retry #{new_count}/#{max_retries}, next attempt in #{wait_minutes}m"
schedule_imap_retry(new_count, max_retries)
end
end
@@ -110,6 +105,20 @@ class Channel::Email < ApplicationRecord
self.forward_to_email ||= "#{SecureRandom.hex}@#{account.inbound_email_domain}"
end
def imap_backoff_max_retries
max_interval = GlobalConfigService.load('IMAP_BACKOFF_MAX_INTERVAL_MINUTES', 5).to_i
max_count = GlobalConfigService.load('IMAP_BACKOFF_MAX_INTERVAL_COUNT', 10).to_i
(max_interval - 1) + max_count
end
def schedule_imap_retry(new_count, max_retries)
max_interval = GlobalConfigService.load('IMAP_BACKOFF_MAX_INTERVAL_MINUTES', 5).to_i
wait_minutes = [new_count, max_interval].min
::Redis::Alfred.set(imap_retry_count_key, new_count.to_s)
::Redis::Alfred.set(imap_retry_after_key, wait_minutes.minutes.from_now.to_f.to_s)
Rails.logger.warn "Error for email channel - #{inbox.id} backoff retry #{new_count}/#{max_retries}, next attempt in #{wait_minutes}m"
end
def imap_retry_count_key
format(::Redis::Alfred::IMAP_BACKOFF_RETRY_COUNT, channel_id: id)
end
@@ -0,0 +1 @@
class Imap::AuthenticationError < StandardError; end
+13
View File
@@ -96,6 +96,19 @@
locked: false
# ------- End of Account Related Config ------- #
# ------- IMAP Backoff Related Config ------- #
- name: IMAP_BACKOFF_MAX_INTERVAL_MINUTES
display_title: 'IMAP Backoff Max Interval (minutes)'
description: 'Maximum wait time in minutes between IMAP retry attempts before the backoff plateaus'
value: 5
locked: false
- name: IMAP_BACKOFF_MAX_INTERVAL_COUNT
display_title: 'IMAP Backoff Max Retry Count'
description: 'Number of additional retries at the maximum interval before prompting reauthorization'
value: 10
locked: false
# ------- End of IMAP Backoff Related Config ------- #
# ------- Email Related Config ------- #
- name: MAILER_INBOUND_EMAIL_DOMAIN
display_title: 'Inbound Email Domain'
-2
View File
@@ -1,7 +1,5 @@
require 'net/imap'
class Imap::AuthenticationError < StandardError; end
module ExceptionList
REST_CLIENT_EXCEPTIONS = [RestClient::NotFound, RestClient::GatewayTimeout, RestClient::BadRequest,
RestClient::MethodNotAllowed, RestClient::Forbidden, RestClient::InternalServerError,