Merge "Reload latest SHA1 from local when filtering RemoteRefUpdate" into stable-3.4
diff --git a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilter.java b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilter.java
index 98f4897..c9300c8 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilter.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilter.java
@@ -27,6 +27,7 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
+import java.util.Optional;
import java.util.Random;
import java.util.Set;
import java.util.stream.Collectors;
@@ -66,19 +67,23 @@
gitRepositoryManager.openRepository(Project.nameKey(projectName))) {
List<RemoteRefUpdate> filteredRefUpdates =
remoteUpdatesList.stream()
- .filter(
+ .map(
refUpdate -> {
- boolean refUpToDate = isUpToDateWithRetry(projectName, repository, refUpdate);
- if (!refUpToDate) {
+ Optional<RemoteRefUpdate> updatedRefUpdate =
+ isUpToDateWithRetry(projectName, repository, refUpdate);
+ if (!updatedRefUpdate.isPresent()) {
repLog.warn(
- "{} is not up-to-date with the shared-refdb and thus will NOT BE replicated",
+ "{} is not up-to-date with the shared-refdb and thus will NOT BE"
+ + " replicated",
refUpdate);
if (refUpdate.getSrcRef().endsWith(REF_META_SUFFIX)) {
outdatedChanges.add(getRootChangeRefPrefix(refUpdate.getSrcRef()));
}
}
- return refUpToDate;
+ return updatedRefUpdate;
})
+ .filter(Optional::isPresent)
+ .map(Optional::get)
.collect(Collectors.toList());
return filteredRefUpdates.stream()
@@ -102,37 +107,56 @@
}
}
- private boolean isUpToDateWithRetry(
+ private Optional<RemoteRefUpdate> isUpToDateWithRetry(
String projectName, Repository repository, RemoteRefUpdate refUpdate) {
String ref = refUpdate.getSrcRef();
try {
if (sharedRefDb.isUpToDate(
Project.nameKey(projectName),
new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, ref, refUpdate.getNewObjectId()))) {
- return true;
+ return Optional.of(refUpdate);
}
randomSleepForMitigatingConditionWhereLocalRefHaveJustBeenChanged(
projectName, refUpdate, ref);
+ ObjectId reloadedNewObjectId = getNotNullExactRef(repository, ref);
+ RemoteRefUpdate refUpdateReloaded =
+ newRemoteRefUpdateWithObjectId(repository, refUpdate, reloadedNewObjectId);
return sharedRefDb.isUpToDate(
- Project.nameKey(projectName),
- new ObjectIdRef.Unpeeled(Ref.Storage.NETWORK, ref, getNotNullExactRef(repository, ref)));
+ Project.nameKey(projectName),
+ new ObjectIdRef.Unpeeled(
+ Ref.Storage.NETWORK, ref, refUpdateReloaded.getNewObjectId()))
+ ? Optional.of(refUpdateReloaded)
+ : Optional.empty();
} catch (GlobalRefDbLockException gle) {
String message =
String.format("%s is locked on shared-refdb and thus will NOT BE replicated", ref);
repLog.error(message);
logger.atSevere().withCause(gle).log(message);
- return false;
+ return Optional.empty();
} catch (IOException ioe) {
String message =
String.format("Error while extracting ref '%s' for project '%s'", ref, projectName);
repLog.error(message);
logger.atSevere().withCause(ioe).log(message);
- return false;
+ return Optional.empty();
}
}
+ private RemoteRefUpdate newRemoteRefUpdateWithObjectId(
+ Repository localDb, RemoteRefUpdate refUpdate, ObjectId reloadedNewObjectId)
+ throws IOException {
+ return new RemoteRefUpdate(
+ localDb,
+ refUpdate.getSrcRef(),
+ reloadedNewObjectId,
+ refUpdate.getRemoteName(),
+ refUpdate.isForceUpdate(),
+ null,
+ refUpdate.getExpectedOldObjectId());
+ }
+
private void randomSleepForMitigatingConditionWhereLocalRefHaveJustBeenChanged(
String projectName, RemoteRefUpdate refUpdate, String ref) {
int randomSleepTimeMsec =
@@ -140,7 +164,8 @@
+ new Random().nextInt(RANDOM_WAIT_BEFORE_RELOAD_LOCAL_VERSION_MS);
repLog.debug(
String.format(
- "'%s' is not up-to-date for project '%s' [local='%s']. Reload local ref in '%d ms' and re-check",
+ "'%s' is not up-to-date for project '%s' [local='%s']. Reload local ref in '%d ms' and"
+ + " re-check",
ref, projectName, refUpdate.getNewObjectId(), randomSleepTimeMsec));
try {
Thread.sleep(randomSleepTimeMsec);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilterTest.java b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilterTest.java
index 5c3f8f0..b45e1fb 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilterTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/multisite/validation/MultisiteReplicationPushFilterTest.java
@@ -102,7 +102,10 @@
@Test
public void shouldLoadLocalVersionAndNotFilter() throws Exception {
- RemoteRefUpdate temporaryOutdated = refUpdate("refs/heads/temporaryOutdated");
+ String refName = "refs/heads/temporaryOutdated";
+ RemoteRefUpdate temporaryOutdated = refUpdate(refName);
+ ObjectId latestObjectId = repo.getRepository().exactRef(refName).getObjectId();
+
List<RemoteRefUpdate> refUpdates = Collections.singletonList(temporaryOutdated);
doReturn(false).doReturn(true).when(sharedRefDatabaseMock).isUpToDate(eq(projectName), any());
@@ -110,7 +113,9 @@
new MultisiteReplicationPushFilter(sharedRefDatabaseMock, gitRepositoryManager);
List<RemoteRefUpdate> filteredRefUpdates = pushFilter.filter(project, refUpdates);
- assertThat(filteredRefUpdates).containsExactly(temporaryOutdated);
+ assertThat(filteredRefUpdates).hasSize(1);
+ assertThat(filteredRefUpdates.get(0).getNewObjectId()).isEqualTo(latestObjectId);
+
verify(sharedRefDatabaseMock, times(2)).isUpToDate(any(), any());
}