DEV: reduce amount of errors logged when notifying on flags (#20472)

Forcing distributed muted to raise when a notify reviewable job is running
leads to excessive errors in the logs under many conditions.

The new pattern

1. Optimises the counting of reviewables so it is a lot faster
2. Holds the distributed lock for 2 minutes (max)


The downside is the job queue can get blocked up when tons of notify
reviewables are running at the same time. However this should be very
rare in the real world, as we only notify when stuff is flagged which
is fairly infrequent.

This also give a fair bit more time for the notifications which may be
a little slow on large sites with tons of mods.
This commit is contained in:
Sam 2023-03-01 08:58:32 +11:00 committed by GitHub
parent def4133d59
commit 654959faa4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 30 deletions

View File

@ -22,13 +22,17 @@ class Jobs::NotifyReviewable < ::Jobs::Base
end end
end end
DistributedMutex.synchronize("notify_reviewable_job", validity: 10, max_get_lock_attempts: 1) do DistributedMutex.synchronize("notify_reviewable_job", validity: 120) do
counts = Hash.new(0) counts = Hash.new(0)
Reviewable
Reviewable.default_visible.pending.each do |r| .default_visible
counts[:admins] += 1 .pending
counts[:moderators] += 1 if r.reviewable_by_moderator? .group(:reviewable_by_moderator, :reviewable_by_group_id)
counts[r.reviewable_by_group_id] += 1 if r.reviewable_by_group_id .pluck(:reviewable_by_moderator, :reviewable_by_group_id, "count(*)")
.each do |reviewable_by_moderator, reviewable_by_group_id, count|
counts[:admins] += count
counts[:moderators] += count if reviewable_by_moderator
counts[reviewable_by_group_id] += count if reviewable_by_group_id
end end
if SiteSetting.legacy_navigation_menu? if SiteSetting.legacy_navigation_menu?

View File

@ -30,28 +30,16 @@ class DistributedMutex
end end
LUA LUA
def self.synchronize( def self.synchronize(key, redis: nil, validity: DEFAULT_VALIDITY, &blk)
key, self.new(key, redis: redis, validity: validity).synchronize(&blk)
redis: nil,
validity: DEFAULT_VALIDITY,
max_get_lock_attempts: nil,
&blk
)
self.new(
key,
redis: redis,
validity: validity,
max_get_lock_attempts: max_get_lock_attempts,
).synchronize(&blk)
end end
def initialize(key, redis: nil, validity: DEFAULT_VALIDITY, max_get_lock_attempts: nil) def initialize(key, redis: nil, validity: DEFAULT_VALIDITY)
@key = key @key = key
@using_global_redis = true if !redis @using_global_redis = true if !redis
@redis = redis || Discourse.redis @redis = redis || Discourse.redis
@mutex = Mutex.new @mutex = Mutex.new
@validity = validity @validity = validity
@max_get_lock_attempts = max_get_lock_attempts
end end
# NOTE wrapped in mutex to maintain its semantics # NOTE wrapped in mutex to maintain its semantics
@ -81,15 +69,11 @@ class DistributedMutex
result result
end end
class MaximumAttemptsExceeded < StandardError
end
private private
attr_reader :key attr_reader :key
attr_reader :redis attr_reader :redis
attr_reader :validity attr_reader :validity
attr_reader :max_get_lock_attempts
def get_lock def get_lock
attempts = 0 attempts = 0
@ -108,10 +92,6 @@ class DistributedMutex
if @using_global_redis && Discourse.recently_readonly? && attempts > CHECK_READONLY_ATTEMPTS if @using_global_redis && Discourse.recently_readonly? && attempts > CHECK_READONLY_ATTEMPTS
raise Discourse::ReadOnly raise Discourse::ReadOnly
end end
if max_get_lock_attempts && attempts > max_get_lock_attempts
raise DistributedMutex::MaximumAttemptsExceeded
end
end end
end end