Listen to GitBatchRefUpdateListener for a set of events
When replicating a set of events, prefer to listen to a group
of ref-update events together, so that they can be sorted by
passing the /meta refs at the end of the calls.
Bug: Issue 16608
Change-Id: I71d6d763e46ea143bd0eef227991da9b15a82554
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java
index cd19be4..08a402e 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationModule.java
@@ -19,7 +19,7 @@
import com.google.common.eventbus.EventBus;
import com.google.gerrit.extensions.annotations.Exports;
import com.google.gerrit.extensions.config.CapabilityDefinition;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
import com.google.gerrit.extensions.events.HeadUpdatedListener;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.events.ProjectDeletedListener;
@@ -123,7 +123,7 @@
.annotatedWith(UniqueAnnotations.create())
.to(ReplicationQueue.class);
- DynamicSet.bind(binder(), GitReferenceUpdatedListener.class).to(ReplicationQueue.class);
+ DynamicSet.bind(binder(), GitBatchRefUpdateListener.class).to(ReplicationQueue.class);
bind(ConfigParser.class).to(SourceConfigParser.class).in(Scopes.SINGLETON);
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java
index f5b27ee..990c82c 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueue.java
@@ -20,7 +20,7 @@
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.Project.NameKey;
import com.google.gerrit.entities.RefNames;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
import com.google.gerrit.extensions.events.HeadUpdatedListener;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.events.ProjectDeletedListener;
@@ -65,7 +65,7 @@
public class ReplicationQueue
implements ObservableQueue,
LifecycleListener,
- GitReferenceUpdatedListener,
+ GitBatchRefUpdateListener,
ProjectDeletedListener,
HeadUpdatedListener {
@@ -147,17 +147,24 @@
}
@Override
- public void onGitReferenceUpdated(GitReferenceUpdatedListener.Event event) {
- if (isRefToBeReplicated(event.getRefName())) {
- repLog.info(
- "Ref event received: {} on project {}:{} - {} => {}",
- refUpdateType(event),
- event.getProjectName(),
- event.getRefName(),
- event.getOldObjectId(),
- event.getNewObjectId());
- fire(ReferenceUpdatedEvent.from(event));
- }
+ public void onGitBatchRefUpdate(GitBatchRefUpdateListener.Event event) {
+ event.getUpdatedRefs().stream()
+ .sorted(ReplicationQueue::sortByMetaRefAsLast)
+ .forEachOrdered(
+ updateRef -> {
+ String refName = updateRef.getRefName();
+
+ if (isRefToBeReplicated(refName)) {
+ repLog.info(
+ "Ref event received: {} on project {}:{} - {} => {}",
+ refUpdateType(updateRef),
+ event.getProjectName(),
+ refName,
+ updateRef.getOldObjectId(),
+ updateRef.getNewObjectId());
+ fire(ReferenceUpdatedEvent.from(event.getProjectName(), updateRef));
+ }
+ });
}
@Override
@@ -170,11 +177,17 @@
source.getApis().forEach(apiUrl -> source.scheduleDeleteProject(apiUrl, project)));
}
- private static String refUpdateType(GitReferenceUpdatedListener.Event event) {
- String forcedPrefix = event.isNonFastForward() ? "FORCED " : " ";
- if (event.isCreate()) {
+ private static int sortByMetaRefAsLast(UpdatedRef a, @SuppressWarnings("unused") UpdatedRef b) {
+ repLog.info("sortByMetaRefAsLast(" + a.getRefName() + " <=> " + b.getRefName());
+ return Boolean.compare(
+ RefNames.isNoteDbMetaRef(a.getRefName()), RefNames.isNoteDbMetaRef(b.getRefName()));
+ }
+
+ private static String refUpdateType(UpdatedRef updateRef) {
+ String forcedPrefix = updateRef.isNonFastForward() ? "FORCED " : " ";
+ if (updateRef.isCreate()) {
return forcedPrefix + "CREATE";
- } else if (event.isDelete()) {
+ } else if (updateRef.isDelete()) {
return forcedPrefix + "DELETE";
} else {
return forcedPrefix + "UPDATE";
@@ -518,12 +531,12 @@
projectName, refName, objectId, isDelete);
}
- static ReferenceUpdatedEvent from(GitReferenceUpdatedListener.Event event) {
+ static ReferenceUpdatedEvent from(String projectName, UpdatedRef updateRef) {
return ReferenceUpdatedEvent.create(
- event.getProjectName(),
- event.getRefName(),
- ObjectId.fromString(event.getNewObjectId()),
- event.isDelete());
+ projectName,
+ updateRef.getRefName(),
+ ObjectId.fromString(updateRef.getNewObjectId()),
+ updateRef.isDelete());
}
public abstract String projectName();
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/FakeGitReferenceUpdatedEvent.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/FakeGitReferenceUpdatedEvent.java
index 43331dc..69549aa 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/FakeGitReferenceUpdatedEvent.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/FakeGitReferenceUpdatedEvent.java
@@ -17,10 +17,13 @@
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.common.AccountInfo;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener.UpdatedRef;
+import java.util.Set;
+import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.transport.ReceiveCommand;
-public class FakeGitReferenceUpdatedEvent implements GitReferenceUpdatedListener.Event {
+public class FakeGitReferenceUpdatedEvent implements GitBatchRefUpdateListener.Event {
private final String projectName;
private final String ref;
private final String oldObjectId;
@@ -46,36 +49,6 @@
}
@Override
- public String getRefName() {
- return ref;
- }
-
- @Override
- public String getOldObjectId() {
- return oldObjectId;
- }
-
- @Override
- public String getNewObjectId() {
- return newObjectId;
- }
-
- @Override
- public boolean isCreate() {
- return type == ReceiveCommand.Type.CREATE;
- }
-
- @Override
- public boolean isDelete() {
- return type == ReceiveCommand.Type.DELETE;
- }
-
- @Override
- public boolean isNonFastForward() {
- return type == ReceiveCommand.Type.UPDATE_NONFASTFORWARD;
- }
-
- @Override
public AccountInfo getUpdater() {
return null;
}
@@ -91,4 +64,46 @@
public NotifyHandling getNotify() {
return NotifyHandling.ALL;
}
+
+ @Override
+ public Set<UpdatedRef> getUpdatedRefs() {
+ return Set.of(
+ new GitBatchRefUpdateListener.UpdatedRef() {
+
+ @Override
+ public String getRefName() {
+ return ref;
+ }
+
+ @Override
+ public String getOldObjectId() {
+ return ObjectId.zeroId().getName();
+ }
+
+ @Override
+ public String getNewObjectId() {
+ return newObjectId;
+ }
+
+ @Override
+ public boolean isCreate() {
+ return type == ReceiveCommand.Type.CREATE;
+ }
+
+ @Override
+ public boolean isDelete() {
+ return type == ReceiveCommand.Type.DELETE;
+ }
+
+ @Override
+ public boolean isNonFastForward() {
+ return type == ReceiveCommand.Type.UPDATE_NONFASTFORWARD;
+ }
+ });
+ }
+
+ @Override
+ public Set<String> getRefNames() {
+ return Set.of(ref);
+ }
}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationFanoutConfigIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationFanoutConfigIT.java
index ee5876f..ff8265f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationFanoutConfigIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationFanoutConfigIT.java
@@ -27,7 +27,7 @@
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.projects.BranchInput;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.replication.AutoReloadConfigDecorator;
@@ -105,14 +105,14 @@
String sourceRef = pushResult.getPatchSet().refName();
ReplicationQueue pullReplicationQueue = getInstance(ReplicationQueue.class);
- GitReferenceUpdatedListener.Event event =
+ GitBatchRefUpdateListener.Event event =
new FakeGitReferenceUpdatedEvent(
project,
sourceRef,
ObjectId.zeroId().getName(),
sourceCommit.getId().getName(),
ReceiveCommand.Type.CREATE);
- pullReplicationQueue.onGitReferenceUpdated(event);
+ pullReplicationQueue.onGitBatchRefUpdate(event);
try (Repository repo = repoManager.openRepository(project)) {
waitUntil(() -> checkedGetRef(repo, sourceRef) != null);
@@ -141,14 +141,14 @@
RevCommit sourceCommit = pushResult.getCommit();
final String sourceRef = pushResult.getPatchSet().refName();
ReplicationQueue pullReplicationQueue = getInstance(ReplicationQueue.class);
- GitReferenceUpdatedListener.Event event =
+ GitBatchRefUpdateListener.Event event =
new FakeGitReferenceUpdatedEvent(
project,
sourceRef,
ObjectId.zeroId().getName(),
sourceCommit.getId().getName(),
ReceiveCommand.Type.CREATE);
- pullReplicationQueue.onGitReferenceUpdated(event);
+ pullReplicationQueue.onGitBatchRefUpdate(event);
try (Repository repo = repoManager.openRepository(project)) {
waitUntil(() -> checkedGetRef(repo, sourceRef) != null);
@@ -174,14 +174,14 @@
ReplicationQueue pullReplicationQueue =
plugin.getSysInjector().getInstance(ReplicationQueue.class);
- GitReferenceUpdatedListener.Event event =
+ GitBatchRefUpdateListener.Event event =
new FakeGitReferenceUpdatedEvent(
project,
newBranch,
ObjectId.zeroId().getName(),
branchRevision,
ReceiveCommand.Type.CREATE);
- pullReplicationQueue.onGitReferenceUpdated(event);
+ pullReplicationQueue.onGitBatchRefUpdate(event);
try (Repository repo = repoManager.openRepository(project);
Repository sourceRepo = repoManager.openRepository(project)) {
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java
index 86b22b2..6fd5cb3 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationIT.java
@@ -30,7 +30,7 @@
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.projects.BranchInput;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
import com.google.gerrit.extensions.events.HeadUpdatedListener;
import com.google.gerrit.extensions.events.ProjectDeletedListener;
import com.google.gerrit.extensions.restapi.RestApiException;
@@ -91,14 +91,14 @@
String sourceRef = pushResult.getPatchSet().refName();
ReplicationQueue pullReplicationQueue = getInstance(ReplicationQueue.class);
- GitReferenceUpdatedListener.Event event =
+ GitBatchRefUpdateListener.Event event =
new FakeGitReferenceUpdatedEvent(
project,
sourceRef,
ObjectId.zeroId().getName(),
sourceCommit.getId().getName(),
ReceiveCommand.Type.CREATE);
- pullReplicationQueue.onGitReferenceUpdated(event);
+ pullReplicationQueue.onGitBatchRefUpdate(event);
try (Repository repo = repoManager.openRepository(project)) {
waitUntil(() -> checkedGetRef(repo, sourceRef) != null);
@@ -124,14 +124,14 @@
ReplicationQueue pullReplicationQueue =
plugin.getSysInjector().getInstance(ReplicationQueue.class);
- GitReferenceUpdatedListener.Event event =
+ GitBatchRefUpdateListener.Event event =
new FakeGitReferenceUpdatedEvent(
project,
newBranch,
ObjectId.zeroId().getName(),
branchRevision,
ReceiveCommand.Type.CREATE);
- pullReplicationQueue.onGitReferenceUpdated(event);
+ pullReplicationQueue.onGitBatchRefUpdate(event);
try (Repository repo = repoManager.openRepository(project);
Repository sourceRepo = repoManager.openRepository(project)) {
@@ -167,14 +167,14 @@
ReplicationQueue pullReplicationQueue =
plugin.getSysInjector().getInstance(ReplicationQueue.class);
- GitReferenceUpdatedListener.Event event =
+ GitBatchRefUpdateListener.Event event =
new FakeGitReferenceUpdatedEvent(
project,
newBranch,
ObjectId.zeroId().getName(),
branchRevision,
ReceiveCommand.Type.CREATE);
- pullReplicationQueue.onGitReferenceUpdated(event);
+ pullReplicationQueue.onGitBatchRefUpdate(event);
try (Repository repo = repoManager.openRepository(project)) {
waitUntil(() -> checkedGetRef(repo, newBranch) != null);
@@ -193,14 +193,14 @@
assertThat(pushedRefs).hasSize(1);
assertThat(pushedRefs.iterator().next().getStatus()).isEqualTo(Status.OK);
- GitReferenceUpdatedListener.Event forcedPushEvent =
+ GitBatchRefUpdateListener.Event forcedPushEvent =
new FakeGitReferenceUpdatedEvent(
project,
newBranch,
branchRevision,
amendedCommit.getId().getName(),
ReceiveCommand.Type.UPDATE_NONFASTFORWARD);
- pullReplicationQueue.onGitReferenceUpdated(forcedPushEvent);
+ pullReplicationQueue.onGitBatchRefUpdate(forcedPushEvent);
try (Repository repo = repoManager.openRepository(project);
Repository sourceRepo = repoManager.openRepository(project)) {
@@ -232,14 +232,14 @@
String sourceRef = pushResult.getPatchSet().refName();
ReplicationQueue pullReplicationQueue = getInstance(ReplicationQueue.class);
- GitReferenceUpdatedListener.Event event =
+ GitBatchRefUpdateListener.Event event =
new FakeGitReferenceUpdatedEvent(
project,
sourceRef,
ObjectId.zeroId().getName(),
sourceCommit.getId().getName(),
ReceiveCommand.Type.CREATE);
- pullReplicationQueue.onGitReferenceUpdated(event);
+ pullReplicationQueue.onGitBatchRefUpdate(event);
try (Repository repo = repoManager.openRepository(project)) {
waitUntil(() -> checkedGetRef(repo, sourceRef) != null);
@@ -273,14 +273,14 @@
ReplicationQueue pullReplicationQueue =
plugin.getSysInjector().getInstance(ReplicationQueue.class);
- GitReferenceUpdatedListener.Event event =
+ GitBatchRefUpdateListener.Event event =
new FakeGitReferenceUpdatedEvent(
project,
newBranch,
ObjectId.zeroId().getName(),
branchRevision,
ReceiveCommand.Type.CREATE);
- pullReplicationQueue.onGitReferenceUpdated(event);
+ pullReplicationQueue.onGitBatchRefUpdate(event);
try (Repository repo = repoManager.openRepository(project);
Repository sourceRepo = repoManager.openRepository(project)) {
@@ -364,14 +364,14 @@
String sourceRef = pushResult.getPatchSet().refName();
ReplicationQueue pullReplicationQueue = getInstance(ReplicationQueue.class);
- GitReferenceUpdatedListener.Event event =
+ GitBatchRefUpdateListener.Event event =
new FakeGitReferenceUpdatedEvent(
project,
sourceRef,
ObjectId.zeroId().getName(),
sourceCommit.getId().getName(),
ReceiveCommand.Type.CREATE);
- pullReplicationQueue.onGitReferenceUpdated(event);
+ pullReplicationQueue.onGitBatchRefUpdate(event);
try (Repository repo = repoManager.openRepository(project)) {
waitUntil(() -> checkedGetRef(repo, sourceRef) != null);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationWithGitHttpTransportProtocolIT.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationWithGitHttpTransportProtocolIT.java
index d8e5947..2d1f51f 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationWithGitHttpTransportProtocolIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/PullReplicationWithGitHttpTransportProtocolIT.java
@@ -21,7 +21,7 @@
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.acceptance.UseLocalDisk;
import com.google.gerrit.acceptance.config.GerritConfig;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
import java.io.IOException;
import java.util.List;
import java.util.Optional;
@@ -82,14 +82,14 @@
String sourceRef = pushResult.getPatchSet().refName();
ReplicationQueue pullReplicationQueue = getInstance(ReplicationQueue.class);
- GitReferenceUpdatedListener.Event event =
+ GitBatchRefUpdateListener.Event event =
new FakeGitReferenceUpdatedEvent(
project,
sourceRef,
ObjectId.zeroId().getName(),
sourceCommit.getId().getName(),
ReceiveCommand.Type.CREATE);
- pullReplicationQueue.onGitReferenceUpdated(event);
+ pullReplicationQueue.onGitBatchRefUpdate(event);
try (Repository repo = repoManager.openRepository(project)) {
waitUntil(() -> checkedGetRef(repo, sourceRef) != null);
diff --git a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java
index 927aec2..e7de264 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/replication/pull/ReplicationQueueTest.java
@@ -21,6 +21,7 @@
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.lenient;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
@@ -33,8 +34,8 @@
import com.google.gerrit.entities.Project;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.common.AccountInfo;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
-import com.google.gerrit.extensions.events.GitReferenceUpdatedListener.Event;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener;
+import com.google.gerrit.extensions.events.GitBatchRefUpdateListener.UpdatedRef;
import com.google.gerrit.extensions.events.ProjectDeletedListener;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.metrics.DisabledMetricMaker;
@@ -54,6 +55,8 @@
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
import org.apache.http.client.ClientProtocolException;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.lib.ObjectId;
@@ -64,6 +67,7 @@
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
import org.mockito.Captor;
+import org.mockito.InOrder;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
@@ -161,57 +165,84 @@
@Test
public void shouldCallSendObjectWhenMetaRef() throws ClientProtocolException, IOException {
- Event event = new TestEvent("refs/changes/01/1/meta");
+ TestEvent event = new TestEvent("refs/changes/01/1/meta");
objectUnderTest.start();
- objectUnderTest.onGitReferenceUpdated(event);
+ objectUnderTest.onGitBatchRefUpdate(event);
verify(fetchRestApiClient).callSendObjects(any(), anyString(), any(), any());
}
@Test
public void shouldCallInitProjectWhenProjectIsMissing() throws IOException {
- Event event = new TestEvent("refs/changes/01/1/meta");
+ TestEvent event = new TestEvent("refs/changes/01/1/meta");
when(httpResult.isSuccessful()).thenReturn(false);
when(httpResult.isProjectMissing(any())).thenReturn(true);
when(source.isCreateMissingRepositories()).thenReturn(true);
objectUnderTest.start();
- objectUnderTest.onGitReferenceUpdated(event);
+ objectUnderTest.onGitBatchRefUpdate(event);
verify(fetchRestApiClient).initProject(any(), any());
}
@Test
public void shouldNotCallInitProjectWhenReplicateNewRepositoriesNotSet() throws IOException {
- Event event = new TestEvent("refs/changes/01/1/meta");
+ TestEvent event = new TestEvent("refs/changes/01/1/meta");
when(httpResult.isSuccessful()).thenReturn(false);
when(httpResult.isProjectMissing(any())).thenReturn(true);
when(source.isCreateMissingRepositories()).thenReturn(false);
objectUnderTest.start();
- objectUnderTest.onGitReferenceUpdated(event);
+ objectUnderTest.onGitBatchRefUpdate(event);
verify(fetchRestApiClient, never()).initProject(any(), any());
}
@Test
public void shouldCallSendObjectWhenPatchSetRef() throws ClientProtocolException, IOException {
- Event event = new TestEvent("refs/changes/01/1/1");
+ TestEvent event = new TestEvent("refs/changes/01/1/1");
objectUnderTest.start();
- objectUnderTest.onGitReferenceUpdated(event);
+ objectUnderTest.onGitBatchRefUpdate(event);
verify(fetchRestApiClient).callSendObjects(any(), anyString(), any(), any());
}
@Test
+ public void shouldCallSendObjectReorderingRefsHavingMetaAtTheEnd()
+ throws ClientProtocolException, IOException {
+ sendRefUpdatedEvents("refs/changes/01/1/meta", "refs/changes/01/1/1");
+ verifySendObjectOrdering("refs/changes/01/1/1", "refs/changes/01/1/meta");
+ }
+
+ @Test
+ public void shouldCallSendObjectKeepingMetaAtTheEnd()
+ throws ClientProtocolException, IOException {
+ sendRefUpdatedEvents("refs/changes/01/1/1", "refs/changes/01/1/meta");
+ verifySendObjectOrdering("refs/changes/01/1/1", "refs/changes/01/1/meta");
+ }
+
+ private void sendRefUpdatedEvents(String firstRef, String secondRef) {
+ objectUnderTest.start();
+ objectUnderTest.onGitBatchRefUpdate(new TestEvent(firstRef, secondRef));
+ }
+
+ private void verifySendObjectOrdering(String firstRef, String secondRef)
+ throws ClientProtocolException, IOException {
+ InOrder inOrder = inOrder(fetchRestApiClient);
+
+ inOrder.verify(fetchRestApiClient).callSendObjects(any(), eq(firstRef), any(), any());
+ inOrder.verify(fetchRestApiClient).callSendObjects(any(), eq(secondRef), any(), any());
+ }
+
+ @Test
public void shouldFallbackToCallFetchWhenIOException()
throws ClientProtocolException, IOException, LargeObjectException {
- Event event = new TestEvent("refs/changes/01/1/meta");
+ TestEvent event = new TestEvent("refs/changes/01/1/meta");
objectUnderTest.start();
when(revReader.read(any(), any(), anyString(), anyInt())).thenThrow(IOException.class);
- objectUnderTest.onGitReferenceUpdated(event);
+ objectUnderTest.onGitBatchRefUpdate(event);
verify(fetchRestApiClient).callFetch(any(), anyString(), any());
}
@@ -219,12 +250,12 @@
@Test
public void shouldFallbackToCallFetchWhenLargeRef()
throws ClientProtocolException, IOException, LargeObjectException {
- Event event = new TestEvent("refs/changes/01/1/1");
+ TestEvent event = new TestEvent("refs/changes/01/1/1");
objectUnderTest.start();
when(revReader.read(any(), any(), anyString(), anyInt())).thenReturn(Optional.empty());
- objectUnderTest.onGitReferenceUpdated(event);
+ objectUnderTest.onGitBatchRefUpdate(event);
verify(fetchRestApiClient).callFetch(any(), anyString(), any());
}
@@ -232,7 +263,7 @@
@Test
public void shouldFallbackToCallFetchWhenParentObjectIsMissing()
throws ClientProtocolException, IOException {
- Event event = new TestEvent("refs/changes/01/1/1");
+ TestEvent event = new TestEvent("refs/changes/01/1/1");
objectUnderTest.start();
when(httpResult.isSuccessful()).thenReturn(false);
@@ -240,7 +271,7 @@
when(fetchRestApiClient.callSendObjects(any(), anyString(), any(), any()))
.thenReturn(httpResult);
- objectUnderTest.onGitReferenceUpdated(event);
+ objectUnderTest.onGitBatchRefUpdate(event);
verify(fetchRestApiClient).callFetch(any(), anyString(), any());
}
@@ -248,7 +279,7 @@
@Test
public void shouldFallbackToApplyAllParentObjectsWhenParentObjectIsMissingOnMetaRef()
throws ClientProtocolException, IOException {
- Event event = new TestEvent("refs/changes/01/1/meta");
+ TestEvent event = new TestEvent("refs/changes/01/1/meta");
objectUnderTest.start();
when(httpResult.isSuccessful()).thenReturn(false, true);
@@ -256,7 +287,7 @@
when(fetchRestApiClient.callSendObjects(any(), anyString(), any(), any()))
.thenReturn(httpResult);
- objectUnderTest.onGitReferenceUpdated(event);
+ objectUnderTest.onGitBatchRefUpdate(event);
verify(fetchRestApiClient, times(2))
.callSendObjects(any(), anyString(), revisionsDataCaptor.capture(), any());
@@ -291,16 +322,16 @@
() -> revReader,
applyObjectMetrics,
fetchMetrics);
- Event event = new TestEvent("refs/multi-site/version");
- objectUnderTest.onGitReferenceUpdated(event);
+ TestEvent event = new TestEvent("refs/multi-site/version");
+ objectUnderTest.onGitBatchRefUpdate(event);
verifyZeroInteractions(wq, rd, dis, sl, fetchClientFactory, accountInfo);
}
@Test
public void shouldSkipEventWhenStarredChangesRef() {
- Event event = new TestEvent("refs/starred-changes/41/2941/1000000");
- objectUnderTest.onGitReferenceUpdated(event);
+ TestEvent event = new TestEvent("refs/starred-changes/41/2941/1000000");
+ objectUnderTest.onGitBatchRefUpdate(event);
verifyZeroInteractions(wq, rd, dis, sl, fetchClientFactory, accountInfo);
}
@@ -365,24 +396,22 @@
return createTempDirectory(prefix);
}
- private class TestEvent implements GitReferenceUpdatedListener.Event {
+ private static class TestEvent implements GitBatchRefUpdateListener.Event {
private String refName;
private String projectName;
- private ObjectId newObjectId;
+ private List<UpdatedRef> refs;
- public TestEvent(String refName) {
- this(refName, "defaultProject", ObjectId.zeroId());
+ public TestEvent(String... refNames) {
+ this(
+ "defaultProject",
+ Arrays.stream(refNames)
+ .map(refName -> updateRef(refName, ObjectId.zeroId()))
+ .collect(Collectors.toUnmodifiableList()));
}
- public TestEvent(String refName, String projectName, ObjectId newObjectId) {
- this.refName = refName;
+ public TestEvent(String projectName, List<UpdatedRef> refs) {
this.projectName = projectName;
- this.newObjectId = newObjectId;
- }
-
- @Override
- public String getRefName() {
- return refName;
+ this.refs = refs;
}
@Override
@@ -396,34 +425,55 @@
}
@Override
- public String getOldObjectId() {
- return ObjectId.zeroId().getName();
- }
-
- @Override
- public String getNewObjectId() {
- return newObjectId.getName();
- }
-
- @Override
- public boolean isCreate() {
- return false;
- }
-
- @Override
- public boolean isDelete() {
- return false;
- }
-
- @Override
- public boolean isNonFastForward() {
- return false;
- }
-
- @Override
public AccountInfo getUpdater() {
return null;
}
+
+ @Override
+ public Set<UpdatedRef> getUpdatedRefs() {
+ return refs.stream().collect(Collectors.toSet());
+ }
+
+ private static final GitBatchRefUpdateListener.UpdatedRef updateRef(
+ String refName, ObjectId refObjectId) {
+ return new GitBatchRefUpdateListener.UpdatedRef() {
+
+ @Override
+ public String getRefName() {
+ return refName;
+ }
+
+ @Override
+ public String getOldObjectId() {
+ return ObjectId.zeroId().getName();
+ }
+
+ @Override
+ public String getNewObjectId() {
+ return refObjectId.getName();
+ }
+
+ @Override
+ public boolean isCreate() {
+ return false;
+ }
+
+ @Override
+ public boolean isDelete() {
+ return false;
+ }
+
+ @Override
+ public boolean isNonFastForward() {
+ return false;
+ }
+ };
+ }
+
+ @Override
+ public Set<String> getRefNames() {
+ return Set.of(refName);
+ }
}
private class FakeProjectDeletedEvent implements ProjectDeletedListener.Event {