Merge branch 'stable-3.9'
* stable-3.9:
Fix ApplyObjectActionIT flakiness due to the wrong ref used
Force async fetch as a fallback for sync replication
Index change asynchronously upon refs replicated event
Address follow-up comments to Change 396868
Introduce wait for replication events to reduce flaky tests
Fail apply-object on change /meta when missing patch-set
Change-Id: Ib0783cb2b0863f7327b415ee9917956e1cc5f1a1
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 2eb26e8..baeb330 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
@@ -774,7 +774,7 @@
private void fireBeforeStartupEvents() {
Set<String> eventsReplayed = new HashSet<>();
ReferenceBatchUpdatedEvent event;
- while ((event = beforeStartupEventsQueue.poll()) != null) {
+ while ((event = beforeStartupEventsQueue.peek()) != null) {
String eventKey =
String.format(
"%s:%s",
@@ -787,6 +787,7 @@
fire(event);
eventsReplayed.add(eventKey);
}
+ beforeStartupEventsQueue.remove(event);
}
}
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationAction.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationAction.java
index 6c24cbc..a69afa4 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationAction.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/api/ProjectInitializationAction.java
@@ -27,12 +27,15 @@
import com.google.common.net.MediaType;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
+import com.google.gerrit.extensions.events.NewProjectCreatedListener;
+import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.Url;
import com.google.gerrit.index.project.ProjectIndexer;
import com.google.gerrit.server.CurrentUser;
+import com.google.gerrit.server.extensions.events.AbstractNoNotifyEvent;
import com.google.gerrit.server.permissions.GlobalPermission;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackendException;
@@ -70,6 +73,7 @@
private final ProjectIndexer projectIndexer;
private final ApplyObjectCommand applyObjectCommand;
private final ProjectCache projectCache;
+ private final DynamicSet<NewProjectCreatedListener> newProjectCreatedListeners;
@Inject
ProjectInitializationAction(
@@ -78,13 +82,15 @@
PermissionBackend permissionBackend,
ProjectIndexer projectIndexer,
ApplyObjectCommand applyObjectCommand,
- ProjectCache projectCache) {
+ ProjectCache projectCache,
+ DynamicSet<NewProjectCreatedListener> newProjectCreatedListeners) {
this.gerritConfigOps = gerritConfigOps;
this.userProvider = userProvider;
this.permissionBackend = permissionBackend;
this.projectIndexer = projectIndexer;
this.applyObjectCommand = applyObjectCommand;
this.projectCache = projectCache;
+ this.newProjectCreatedListeners = newProjectCreatedListeners;
}
@Override
@@ -179,6 +185,10 @@
throw new BadRequestException("Configuration data cannot contain change meta refs", e);
}
projectCache.onCreateProject(Project.nameKey(projectName));
+ // In case pull-replication is used in conjunction with multi-site, by convention the remote
+ // label is populated with the instanceId. That's why we are passing input.getLabel()
+ // to the Event to notify
+ notifyListenersOfNewProjectCreation(projectName, input.getLabel());
repLog.info(
"Init project API from {} for {}:{} - {}",
input.getLabel(),
@@ -246,4 +256,38 @@
return false;
}
}
+
+ private void notifyListenersOfNewProjectCreation(String projectName, String instanceId) {
+ NewProjectCreatedListener.Event newProjectCreatedEvent =
+ new Event(RefNames.REFS_CONFIG, projectName, instanceId);
+ newProjectCreatedListeners.forEach(l -> l.onNewProjectCreated(newProjectCreatedEvent));
+ }
+
+ private static class Event extends AbstractNoNotifyEvent
+ implements NewProjectCreatedListener.Event {
+ private final String headName;
+ private final String projectName;
+ private final String instanceId;
+
+ public Event(String headName, String projectName, String maybeInstanceId) {
+ this.headName = headName;
+ this.projectName = projectName;
+ this.instanceId = maybeInstanceId;
+ }
+
+ @Override
+ public String getHeadName() {
+ return headName;
+ }
+
+ @Override
+ public String getProjectName() {
+ return projectName;
+ }
+
+ @Override
+ public String getInstanceId() {
+ return instanceId;
+ }
+ }
}