Class: NonCampaignClickScoringWorker

Inherits:
Object
  • Object
show all
Includes:
Sidekiq::Job
Defined in:
app/workers/non_campaign_click_scoring_worker.rb

Overview

Sidekiq sweep: score clicks on NON-campaign sends — transactional email (quotes,
receipts, order confirmations) and one-off marketing — for security-scanner
traffic, the same way CampaignEmailClickScoringWorker does for campaigns.

Campaigns are scored per-send by a delayed job fired when the CampaignEmail
reaches transmitted. Non-campaign sends have no such hook, so this recurring
sweep (scheduled in config/sidekiq_*_schedule.yml) pools recently-clicked,
still-unscored, non-campaign recipients and runs Communication::ClickBotScorer
over them as one set. That picks up cross-send shared-IP fan-out and the
fleet-wide canary scanner-IP registry — which matters because transactional email
deliberately carries no canary of its own, so it relies on scanner IPs learned
from marketing/campaign sends plus the per-recipient burst signal.

Idempotent: the machine_clicked IS NULL filter means each recipient is scored
once, and re-running only picks up newly-settled recipients.

Constant Summary collapse

SETTLE =

Let a send's clicks settle before scoring (mirrors the campaign delay intent).

2.hours
LOOKBACK =

How far back to look for unscored clicked recipients — bounds the scan via the
email-links created_at BRIN index.

2.days

Instance Method Summary collapse

Instance Method Details

#performHash?

Returns ClickBotScorer summary, or nil when there is nothing to score.

Returns:

  • (Hash, nil)

    ClickBotScorer summary, or nil when there is nothing to score



30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'app/workers/non_campaign_click_scoring_worker.rb', line 30

def perform
  recipient_ids = CommunicationRecipientEmailLink
                  .where(created_at: LOOKBACK.ago..SETTLE.ago)
                  .distinct.pluck(:communication_recipient_id)
  return if recipient_ids.empty?

  recipients = CommunicationRecipient
               .where(id: recipient_ids, machine_clicked: nil)
               .where.missing(:campaign_delivery)

  Communication::ClickBotScorer.new(
    recipients, extra_scanner_ips: Communication::ClickBotScorer.known_scanner_ips
  ).process
end