From 8e150b5eb81658da6d933a39b3f53ed520e40763 Mon Sep 17 00:00:00 2001 From: Jens Kraemer Date: Thu, 6 Jul 2023 16:00:10 +0200 Subject: [PATCH] retry in case of stale issue during Issue.update_versions --- app/models/issue.rb | 14 +++++++++++--- test/unit/issue_test.rb | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/app/models/issue.rb b/app/models/issue.rb index e23b02647a..e165f414cc 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -1891,9 +1891,17 @@ class Issue < ActiveRecord::Base next if issue.project.nil? || issue.fixed_version.nil? unless issue.project.shared_versions.include?(issue.fixed_version) - issue.init_journal(User.current) - issue.fixed_version = nil - issue.save + retried = false + begin + issue.init_journal(User.current) + issue.fixed_version = nil + issue.save + rescue ActiveRecord::StaleObjectError + raise if retried + retried = true + issue.reload + retry + end end end end diff --git a/test/unit/issue_test.rb b/test/unit/issue_test.rb index aa2ff82705..bfb35b2642 100644 --- a/test/unit/issue_test.rb +++ b/test/unit/issue_test.rb @@ -3489,6 +3489,41 @@ class IssueTest < ActiveSupport::TestCase end end + def test_change_of_project_parent_should_update_shared_versions_with_derived_priorities + with_settings('parent_issue_priority' => 'derived') do + parent = Project.find 1 + child = Project.find 3 + assert_equal parent, child.parent + assert version = parent.versions.create(name: 'test', sharing: 'descendants') + assert version.persisted? + assert child.shared_versions.include?(version) + + # create a situation where the child issue id is lower than the parent issue id. + # When the parent project is removed, the version inherited from there will be removed from + # both issues. At least on MySQL the record with the lower Id will be processed first. + # + # If this update on the child triggers an update on the parent record (here, due to the derived + # priority), the already loaded parent issue is considered stale when it's version is updated. + assert child_issue = child.issues.first + parent_issue = Issue.create! project: child, subject: 'test', tracker: child_issue.tracker, author: child_issue.author, status: child_issue.status, fixed_version: version + assert child_issue.update fixed_version: version, priority_id: 6, parent: parent_issue + parent_issue.update_column :priority_id, 4 # force a priority update when the version is nullified + + assert child.update parent: nil + + child.reload + assert !child.shared_versions.include?(version) + + child_issue.reload + assert_nil child_issue.fixed_version + assert_equal 6, child_issue.priority_id + + parent_issue.reload + assert_nil parent_issue.fixed_version + assert_equal 6, parent_issue.priority_id + end + end + def test_create_should_not_add_anonymous_as_watcher Role.anonymous.add_permission!(:add_issue_watchers) -- 2.39.0