class Mailings::HourlyThroughput HOUR = 1.hour RECENT = 15.minutes HISTORY_HOURS = 12 def initialize(project, now: Time.current) @project = project @now = now end def sent @sent ||= sent_since(HOUR) end def recent_sent @recent_sent ||= sent_since(RECENT) end def failed @failed ||= recipients.failed.where(updated_at: (@now - HOUR)..@now).count end def drained sent + failed end def hourly_history @hourly_history ||= begin from = (@now - (HISTORY_HOURS - 1).hours).beginning_of_hour keyed = recipients.sent .where(sent_at: from..@now) .pluck(:sent_at) .each_with_object(Hash.new(0)) do |sent_at, counts| counts[sent_at.in_time_zone.beginning_of_hour] += 1 end HISTORY_HOURS.times.map do |index| at = from + index.hours { at: at, count: keyed[at] || 0 } end end end def history_total hourly_history.sum { |bucket| bucket[:count] } end def history_max [hourly_history.map { |bucket| bucket[:count] }.max, 1].max end private def sent_since(window) recipients.sent.where(sent_at: (@now - window)..@now).count end def recipients MailingRecipient.joins(:mailing).merge(Mailing.for_project(@project)) end end