mirror of
https://github.com/discourse/discourse.git
synced 2025-02-06 19:38:24 +00:00
c0293339b8
Previously, Jobs::EnqueueDigestEmails would enqueue a digest job for every user, even if there are no topics to send. The digest job would exit, no email would send, and last_emailed_at would not change. 30 minutes later, Jobs::EnqueueDigestEmails would run again and re-enqueue jobs for the same users. 120fa8ad introduced a temporary mitigation for this issue, by randomly selecting a subset of those users each time. This commit adds a new `digest_attempted_at` column to the `user_stats` table. This column is updated every time a digest job completes for a user. Using this, we can avoid scheduling digest jobs for the same user every 30 minutes. This also removes the random user selection in 120fa8ad, and instead prioritizes users who had digests attempted the longest time ago.
45 lines
1.7 KiB
Ruby
45 lines
1.7 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
module Jobs
|
|
|
|
class EnqueueDigestEmails < ::Jobs::Scheduled
|
|
every 30.minutes
|
|
|
|
def execute(args)
|
|
return if SiteSetting.disable_digest_emails? || SiteSetting.private_email? || SiteSetting.disable_emails == 'yes'
|
|
users = target_user_ids
|
|
|
|
users.each do |user_id|
|
|
::Jobs.enqueue(:user_email, type: :digest, user_id: user_id)
|
|
end
|
|
end
|
|
|
|
def target_user_ids
|
|
# Users who want to receive digest email within their chosen digest email frequency
|
|
query = User
|
|
.real
|
|
.activated
|
|
.not_suspended
|
|
.where(staged: false)
|
|
.joins(:user_option, :user_stat, :user_emails)
|
|
.where("user_options.email_digests")
|
|
.where("user_stats.bounce_score < #{SiteSetting.bounce_score_threshold}")
|
|
.where("user_emails.primary")
|
|
.where("COALESCE(last_emailed_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)")
|
|
.where("COALESCE(user_stats.digest_attempted_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)")
|
|
.where("COALESCE(last_seen_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 MINUTE'::INTERVAL * user_options.digest_after_minutes)")
|
|
.where("COALESCE(last_seen_at, '2010-01-01') >= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * #{SiteSetting.suppress_digest_email_after_days})")
|
|
.order("user_stats.digest_attempted_at ASC NULLS FIRST")
|
|
|
|
# If the site requires approval, make sure the user is approved
|
|
query = query.where("approved OR moderator OR admin") if SiteSetting.must_approve_users?
|
|
|
|
query = query.limit(GlobalSetting.max_digests_enqueued_per_30_mins_per_site)
|
|
|
|
query.pluck(:id)
|
|
end
|
|
|
|
end
|
|
|
|
end
|