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; + } + } }