Merge branch 'stable-3.6' into stable-3.7
* stable-3.6:
Roll back batch ref updates on uncaught throwables
Change-Id: I9201b03728a01d371de7d1c8415b5a8d86f62a45
diff --git a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidator.java b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidator.java
index f461a9a..1e45951 100644
--- a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidator.java
+++ b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidator.java
@@ -157,14 +157,21 @@
try (CloseableSet<AutoCloseable> locks = new CloseableSet<>()) {
final List<RefPair> finalRefsToUpdate = compareAndGetLatestLocalRefs(refsToUpdate, locks);
delegateUpdate.invoke();
+ boolean sharedDbUpdateSucceeded = false;
try {
updateSharedRefDb(batchRefUpdate.getCommands().stream(), finalRefsToUpdate);
+ sharedDbUpdateSucceeded = true;
} catch (Exception e) {
- List<ReceiveCommand> receiveCommands = batchRefUpdate.getCommands();
logger.atWarning().withCause(e).log(
- "Batch ref-update failing because of failure during the global refdb update. Set all commands Result to LOCK_FAILURE [%d]",
- receiveCommands.size());
- rollback(delegateUpdateRollback, finalRefsToUpdate, receiveCommands);
+ "Batch ref-update failed because of failure during the global refdb update.");
+ } finally {
+ if (!sharedDbUpdateSucceeded) {
+ List<ReceiveCommand> receiveCommands = batchRefUpdate.getCommands();
+ logger.atWarning().log(
+ "Batch ref-update failed, set all commands Result to LOCK_FAILURE [%d]",
+ commands.size());
+ rollback(delegateUpdateRollback, finalRefsToUpdate, receiveCommands);
+ }
}
} catch (OutOfSyncException e) {
List<ReceiveCommand> receiveCommands = batchRefUpdate.getCommands();
diff --git a/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidatorTest.java b/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidatorTest.java
index 2c4a1ea..e5d3409 100644
--- a/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidatorTest.java
+++ b/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidatorTest.java
@@ -15,11 +15,13 @@
package com.gerritforge.gerrit.globalrefdb.validation;
import static com.google.common.truth.Truth.assertThat;
+import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static java.util.Collections.singletonList;
import static org.eclipse.jgit.transport.ReceiveCommand.Type.UPDATE;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -180,6 +182,35 @@
}
@Test
+ public void shouldRollbackWhenSharedRefUpdateCompareAndPutThrowsUncaughtThrowable()
+ throws Exception {
+ String REF_NAME = "refs/changes/01/1/meta";
+ BatchRefUpdate batchRefUpdate =
+ newBatchUpdate(singletonList(new ReceiveCommand(A, B, REF_NAME, UPDATE)));
+ BatchRefUpdateValidator batchRefUpdateValidator =
+ getRefValidatorForEnforcement(A_TEST_PROJECT_NAME, tmpRefEnforcement);
+
+ doReturn(SharedRefEnforcement.EnforcePolicy.REQUIRED)
+ .when(batchRefUpdateValidator.refEnforcement)
+ .getPolicy(A_TEST_PROJECT_NAME, REF_NAME);
+ doReturn(true).when(sharedRefDatabase).isUpToDate(any(), any());
+
+ doThrow(TestError.class).when(sharedRefDatabase).compareAndPut(any(), any(), any());
+
+ assertThrows(
+ TestError.class,
+ () ->
+ batchRefUpdateValidator.executeBatchUpdateWithValidation(
+ batchRefUpdate, () -> execute(batchRefUpdate), rollbackFunction));
+
+ verify(rollbackFunction).invoke(any());
+ List<ReceiveCommand> commands = batchRefUpdate.getCommands();
+ assertThat(commands.size()).isEqualTo(1);
+ commands.forEach(
+ (command) -> assertThat(command.getResult()).isEqualTo(ReceiveCommand.Result.LOCK_FAILURE));
+ }
+
+ @Test
public void shouldRollbackRefUpdateWhenRefDbIsNotUpdated() throws Exception {
String REF_NAME = "refs/changes/01/1/meta";
BatchRefUpdate batchRefUpdate =
@@ -266,4 +297,6 @@
public String testBranch() {
return "branch_" + nameRule.getMethodName();
}
+
+ private static class TestError extends Error {}
}