BURs: process BURs sequentially in a single job.

Change the way BURs are processed. Before, we spawned a background job
for each line of the BUR, then processed each job sequentially. Now, we
process the entire BUR sequentially in a single background job.

This means that:

* BURs are truly sequential now. Before certain things like removing
  aliases weren't actually performed in a background job, so they were
  performed out-of-order before everything else in the BUR.

* Before, if an alias or implication line failed, then subsequent alias
  or implication lines would still be processed. This was because each
  alias or implication line was queued as a separate job, so a failure
  of one job didn't block another. Now, if any alias or implication
  fails, the entire BUR will fail and stop processing after that line.
  This may be good or bad, depending on whether we actually need the BUR
  to be processed in order or not.

* Before, BURs were processed inside a database transaction (except for the
  actual updating of posts). Now they're not. This is because we can't
  afford to hold transactions open while processing long-running aliases
  or implications. This means that if BUR fails in the middle when it is
  initially approved, it will be left in a half-complete state. Before
  it would be rolled back and left in a pending state with no changes
  performed.

* Before, only one BUR at a time could be processed. If multiple BURs
  were approved at the same time, then they would queue up and be
  processed one at a time. Now, multiple BURs can be processed at the
  same time. This may be undesirable when processing large BURs, or BURs
  that must be approved in a specific order.

* Before, large tag category changes could time out. This was because
  they weren't actually performed in a background job. Now they are, so
  they shouldn't time out.
This commit is contained in:
evazion
2021-09-19 18:36:12 -05:00
parent 96c5c346ad
commit 9ba84efc07
9 changed files with 87 additions and 99 deletions

View File

@@ -0,0 +1,11 @@
# A job that applies a bulk update request after it is approved.
#
# @see {BulkUpdateRequestProcessor}
# @see {BulkUpdateRequest}
class ProcessBulkUpdateRequestJob < ApplicationJob
retry_on Exception, attempts: 0
def perform(bulk_update_request)
bulk_update_request.processor.process!
end
end

View File

@@ -1,13 +0,0 @@
# A job that processes a single tag alias or implication when a bulk update
# request is approved. One job per alias or implication is spawned. Jobs are
# processed sequentially in the `bulk_update` queue.
class ProcessTagRelationshipJob < ApplicationJob
queue_as :bulk_update
retry_on Exception, attempts: 0
def perform(class_name:, approver:, antecedent_name:, consequent_name:, forum_topic: nil)
relation_class = Kernel.const_get(class_name)
tag_relationship = relation_class.create!(creator: approver, approver: approver, antecedent_name: antecedent_name, consequent_name: consequent_name, forum_topic: forum_topic)
tag_relationship.process!
end
end

View File

@@ -1,23 +0,0 @@
# A job that performs a mass update or tag nuke operation in a bulk update
# request. Jobs in the `bulk_update` queue are processed sequentially.
class TagBatchChangeJob < ApplicationJob
queue_as :bulk_update
def perform(antecedent, consequent)
normalized_antecedent = PostQueryBuilder.new(antecedent).split_query
normalized_consequent = PostQueryBuilder.new(consequent).parse_tag_edit
CurrentUser.scoped(User.system) do
migrate_posts(normalized_antecedent, normalized_consequent)
end
end
def migrate_posts(normalized_antecedent, normalized_consequent)
::Post.system_tag_match(normalized_antecedent.join(" ")).find_each do |post|
post.with_lock do
tags = (post.tag_array - normalized_antecedent + normalized_consequent).join(" ")
post.update(tag_string: tags)
end
end
end
end

View File

@@ -1,9 +0,0 @@
# A job that performs a tag rename or alias operation in a bulk update request.
# Jobs in the `bulk_update` queue are processed sequentially.
class TagRenameJob < ApplicationJob
queue_as :bulk_update
def perform(old_tag_name, new_tag_name)
TagMover.new(old_tag_name, new_tag_name, user: User.system).move!
end
end