Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,10 @@ def initialize(project)
end

def call
ApplicationRecord.transaction do
fix_identifier_if_needed
reset_stale_identifiers
backfill_missing_ids
seed_alias_table
end
fix_identifier_if_needed
ApplicationRecord.transaction { reset_stale_identifiers }
ApplicationRecord.transaction { backfill_missing_ids }
ApplicationRecord.transaction { seed_alias_table }
end

private
Expand All @@ -57,15 +55,8 @@ def fix_identifier_if_needed
# Pure format check — no DB queries.
return if ProjectIdentifiers::IdentifierAutofix::ProblematicIdentifiers.valid_format?(project.identifier)

# Serialize all concurrent identifier assignments with a transaction-level
# advisory lock. The lock is automatically released when the outer
# ApplicationRecord.transaction commits, so the next job waiting on it
# always reads a fully up-to-date exclusion set and can never generate a
# duplicate. Without this, parallel jobs can read the same exclusion set
# before any of them commits, then all pick the same candidate.
OpenProject::Mutex.with_advisory_lock(
Project, "semantic_identifier_generation", transaction: true
) do
# Identifier assignments must run one at a time to avoid conflicts with concurrent renames or conversions.
OpenProject::Mutex.with_advisory_lock(Project, "semantic_identifier_generation") do
assign_semantic_identifier
end
end
Expand Down
Loading