Fix NPE issue from pull replication after configuration auto reload Add missing work queue creation to solve NPE when configuration is auto reloaded. Feature: Issue 12729 Change-Id: Ica4df470ae3f9b3c6f9d50f942b1cb438b1defc3
diff --git a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourcesCollection.java b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourcesCollection.java index 81b77a3..7be4971 100644 --- a/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourcesCollection.java +++ b/src/main/java/com/googlesource/gerrit/plugins/replication/pull/SourcesCollection.java
@@ -21,6 +21,7 @@ import com.google.common.flogger.FluentLogger; import com.google.gerrit.server.git.WorkQueue; import com.google.inject.Inject; +import com.google.inject.Provider; import com.google.inject.Singleton; import com.googlesource.gerrit.plugins.replication.ConfigParser; import com.googlesource.gerrit.plugins.replication.RemoteConfiguration; @@ -36,17 +37,20 @@ private final Source.Factory sourceFactory; private volatile List<Source> sources; private boolean shuttingDown; + private final Provider<ReplicationQueue> replicationQueue; @Inject public SourcesCollection( ReplicationConfig replicationConfig, ConfigParser configParser, Source.Factory sourceFactory, - EventBus eventBus) + EventBus eventBus, + Provider<ReplicationQueue> replicationQueue) throws ConfigInvalidException { this.sourceFactory = sourceFactory; this.sources = allSources(sourceFactory, configParser.parseRemotes(replicationConfig.getConfig())); + this.replicationQueue = replicationQueue; eventBus.register(this); } @@ -109,8 +113,12 @@ logger.atWarning().log("Shutting down: configuration reload ignored"); return; } - - sources = allSources(sourceFactory, sourceConfigurations); - logger.atInfo().log("Configuration reloaded: %d sources", getAll().size()); + try { + replicationQueue.get().stop(); + sources = allSources(sourceFactory, sourceConfigurations); + logger.atInfo().log("Configuration reloaded: %d sources", getAll().size()); + } finally { + replicationQueue.get().start(); + } } }
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 fa99a62..cb5af42 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
@@ -122,6 +122,41 @@ } @Test + public void shouldReplicateNewChangeRefAfterConfigReloaded() throws Exception { + testRepo = cloneProject(createTestProject(project + TEST_REPLICATION_SUFFIX)); + + // Trigger configuration autoreload + AutoReloadConfigDecorator autoReloadConfigDecorator = + getInstance(AutoReloadConfigDecorator.class); + SourcesCollection sources = getInstance(SourcesCollection.class); + remoteConfig.setInt("remote", null, "timeout", 1000); + remoteConfig.save(); + autoReloadConfigDecorator.reload(); + waitUntil(() -> !sources.getAll().isEmpty() && sources.getAll().get(0).getTimeout() == 1000); + + Result pushResult = createChange(); + RevCommit sourceCommit = pushResult.getCommit(); + final String sourceRef = pushResult.getPatchSet().refName(); + ReplicationQueue pullReplicationQueue = getInstance(ReplicationQueue.class); + GitReferenceUpdatedListener.Event event = + new FakeGitReferenceUpdatedEvent( + project, + sourceRef, + ObjectId.zeroId().getName(), + sourceCommit.getId().getName(), + ReceiveCommand.Type.CREATE); + pullReplicationQueue.onGitReferenceUpdated(event); + + try (Repository repo = repoManager.openRepository(project)) { + waitUntil(() -> checkedGetRef(repo, sourceRef) != null); + + Ref targetBranchRef = getRef(repo, sourceRef); + assertThat(targetBranchRef).isNotNull(); + assertThat(targetBranchRef.getObjectId()).isEqualTo(sourceCommit.getId()); + } + } + + @Test public void shouldReplicateNewBranch() throws Exception { String testProjectName = project + TEST_REPLICATION_SUFFIX; createTestProject(testProjectName);