HabitatMap/AirCasting

View on GitHub
app/workers/threshold_alerts_worker.rb

Summary

Maintainability
A
3 hrs
Test Coverage
require 'sidekiq-scheduler'

class ThresholdAlertsWorker
  include Sidekiq::Worker

  def perform
    alerts = ThresholdAlert.all
    Sidekiq.logger.info "[TRSHLD] #{alerts.count} alerts found: #{alerts.inspect}"

    alerts.each do |alert|
      if was_recently_sent?(alert)
        Sidekiq.logger.warn "[TRSHLD] Alert ##{alert.id} skipped, recently sent: #{alert.inspect}"
        next
      end
      # next if was_recently_sent?(alert)

      session = Session.joins(:streams).find_by_uuid(alert.session_uuid)
      unless session
        Sidekiq.logger.warn "[TRSHLD] Alert ##{alert.id} skipped, session with UUID ##{alert.session_uuid} not found: #{alert.inspect}"
        next
      end
      # next unless session

      stream = session.streams.select { |stream| stream.sensor_name == alert.sensor_name }.first
      unless stream
        Sidekiq.logger.warn "[TRSHLD] Alert ##{alert.id} skipped, stream with sensor name '#{alert.sensor_name}' not found: #{alert.inspect}"
        next
      end
      # next unless stream

      date_to_compare = alert.last_email_at || alert.created_at # Those are in UTC
      date_to_compare_local = date_to_compare + alert.timezone_offset

      measurements = stream.measurements.where('time > ?', date_to_compare_local).order('time ASC') # Measurement#time is local
      Sidekiq.logger.info "[TRSHLD] Found #{measurements.count} measurements since #{date_to_compare}: #{measurements.inspect} for alert ##{alert.id}."

      measurements_above_threshold = measurements&.select { |m| m.value > alert.threshold_value }

      unless measurements_above_threshold.empty?
        UserMailer
          .with(
            user: session.user,
            title: session.title,
            sensor: stream.sensor_name,
          )
          .threshold_exceeded_email
          .deliver_later

        alert.update(last_email_at: Time.current)
        Sidekiq.logger.info("[TRSHLD] Alert ##{alert.id} sent: #{alert.inspect}")
      else
        Sidekiq.logger.warn "[TRSHLD] Alert ##{alert.id} skipped, no new measurements above threshold: #{alert.inspect}"
      end
    end
  end

  private

  def was_recently_sent?(alert)
    return false unless alert.last_email_at

    (alert.last_email_at + alert.frequency.hours) > Time.current
  end
end