Fix race condition in checking topic mergeability The list of changes in the topic is looked up using the secondary index, which prepopulates the mergeable field on the ChangeData. This value may be stale, as it is just a boolean yes/no, suitable primarily for rendering the search results list. In particular, it may not reflect the current state of the branch tip, if the ReindexAfterUpdate queue has not yet been fully processed. ActionsIT was hitting this race condition by submitting a change then immediately checking the mergeability of a change conflicting with the new branch tip. The mergeability of this second change should switch from true to false as a result (blocking submission of the whole topic). Because of this race condition, it was indeterminate which mergeability bit would be returned from the search index. The workaround for now is to allow explicitly clearing the mergeable bit in ChangeData. A more robust change would be to tweak the index system to say we want to prepopulate the ChangeData with fewer stored fields from the index. As InternalChangeQuery is used more, this may become more and more important. Change-Id: I847c7896371451b85a05f4d768b805b953b61466
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java index b53d193..66c99f1 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ActionsIT.java
@@ -19,7 +19,6 @@ import com.google.gerrit.acceptance.AbstractDaemonTest; import com.google.gerrit.acceptance.PushOneCommit; import com.google.gerrit.extensions.api.changes.ReviewInput; -import com.google.gerrit.extensions.client.SubmitType; import com.google.gerrit.extensions.common.ActionInfo; import com.google.gerrit.testutil.ConfigSuite;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java index 3cba4be..f7fab69 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
@@ -260,6 +260,11 @@ if (!changeControl.canSubmit()) { return BLOCKED_TOPIC_TOOLTIP; } + // Recheck mergeability rather than using value stored in the index, + // which may be stale. + // TODO(dborowitz): This is ugly; consider providing a way to not read + // stored fields from the index in the first place. + c.setMergeable(null); if (!c.isMergeable()) { return CLICK_FAILURE_OTHER_TOOLTIP; }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java index 3c24dd2..802cf65 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -602,7 +602,7 @@ return submitRecords; } - public void setMergeable(boolean mergeable) { + public void setMergeable(Boolean mergeable) { this.mergeable = mergeable; }