Files
eminuxCRM/app/services/mailings/smtp_gate.rb
T
eminuxandCursor 403fe80d37
CI / scan_js (push) Has been cancelled
CI / scan_ruby (push) Has been cancelled
CI / lint (push) Has been cancelled
Serializza gli invii SMTP su una coda unica per non far chiudere Aruba.
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 12:06:23 +02:00

74 lines
1.4 KiB
Ruby

require "net/smtp"
require "openssl"
class Mailings::SmtpGate
MUTEX = Mutex.new
RETRYABLE = [
EOFError,
IOError,
Errno::ECONNRESET,
Errno::EPIPE,
Errno::ETIMEDOUT,
Net::OpenTimeout,
Net::ReadTimeout,
OpenSSL::SSL::SSLError,
Net::SMTPServerBusy
].freeze
class << self
attr_accessor :min_gap, :max_attempts, :backoff_base
def deliver
MUTEX.synchronize { deliver_locked { yield } }
end
def reset!
MUTEX.synchronize { @last_monotonic = nil }
end
private
def deliver_locked
attempts = 0
begin
wait_min_gap
result = yield
stamp!
result
rescue *RETRYABLE => e
attempts += 1
stamp!
Rails.logger.warn("[smtp-gate] #{e.class}: #{e.message} attempt=#{attempts}/#{max_attempts}")
raise if attempts >= max_attempts
sleep_wait(backoff_base * (2**(attempts - 1)))
retry
end
end
def wait_min_gap
return if min_gap.to_f <= 0 || @last_monotonic.nil?
elapsed = now - @last_monotonic
remaining = min_gap - elapsed
sleep_wait(remaining) if remaining.positive?
end
def stamp!
@last_monotonic = now
end
def now
Process.clock_gettime(Process::CLOCK_MONOTONIC)
end
def sleep_wait(seconds)
sleep(seconds) if seconds.to_f.positive?
end
end
self.min_gap = 0.0
self.max_attempts = 1
self.backoff_base = 0.0
end