Merge branch 'stable-3.2' into stable-3.3
* stable-3.2:
Upgrade bazlets to latest stable-3.2 to build with 3.2.5.1 API
Fix plugin's documentation after 8fb718b
Upgrade bazlets to latest stable-3.1 to build with 3.1.10 API
Change-Id: I0f3d2bca8a2639d488be390f94c73956e02bc667
diff --git a/BUILD b/BUILD
index 3b896ff..5975b31 100644
--- a/BUILD
+++ b/BUILD
@@ -19,7 +19,10 @@
"Implementation-URL: https://gerrit-review.googlesource.com/#/admin/projects/plugins/high-availability",
],
resources = glob(["src/main/resources/**/*"]),
- deps = ["@jgroups//jar"],
+ deps = [
+ "@jgroups//jar",
+ "@global-refdb//jar",
+ ],
)
junit_tests(
@@ -42,6 +45,7 @@
visibility = ["//visibility:public"],
exports = PLUGIN_DEPS + PLUGIN_TEST_DEPS + [
":high-availability__plugin",
+ "@global-refdb//jar",
"@wiremock//jar",
],
)
diff --git a/WORKSPACE b/WORKSPACE
index 83e0599..cdb1696 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -12,7 +12,7 @@
"gerrit_api",
)
-gerrit_api()
+gerrit_api(version = "3.3.0-SNAPSHOT")
load("//:external_plugin_deps.bzl", "external_plugin_deps")
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
index 0f8b43b..cb3f043 100644
--- a/external_plugin_deps.bzl
+++ b/external_plugin_deps.bzl
@@ -12,3 +12,9 @@
artifact = "org.jgroups:jgroups:3.6.15.Final",
sha1 = "755afcfc6c8a8ea1e15ef0073417c0b6e8c6d6e4",
)
+
+ maven_jar(
+ name = "global-refdb",
+ artifact = "com.gerritforge:global-refdb:3.3.0-rc1",
+ sha1 = "1b005b31c27a30ff10de97f903fa2834051bcadf",
+ )
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/Configuration.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/Configuration.java
index 3bd58a3..9af312d 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/Configuration.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/Configuration.java
@@ -17,18 +17,19 @@
import static java.util.concurrent.TimeUnit.HOURS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
+import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDbConfiguration;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.CharMatcher;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.annotations.PluginName;
import com.google.gerrit.server.config.ConfigUtil;
-import com.google.gerrit.server.config.PluginConfigFactory;
import com.google.gerrit.server.config.SitePaths;
import com.google.inject.Inject;
import com.google.inject.Singleton;
+import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
@@ -39,7 +40,10 @@
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
+import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.util.FS;
@Singleton
public class Configuration {
@@ -47,6 +51,7 @@
public static final int DEFAULT_NUM_STRIPED_LOCKS = 10;
public static final int DEFAULT_TIMEOUT_MS = 5000;
+ public static final String PLUGIN_CONFIG_FILE = "high-availability.config";
// common parameter to peerInfo section
static final String PEER_INFO_SECTION = "peerInfo";
@@ -70,6 +75,7 @@
private PeerInfoStatic peerInfoStatic;
private PeerInfoJGroups peerInfoJGroups;
private HealthCheck healthCheck;
+ private final SharedRefDbConfiguration sharedRefDb;
public enum PeerInfoStrategy {
JGROUPS,
@@ -77,9 +83,12 @@
}
@Inject
- Configuration(
- PluginConfigFactory pluginConfigFactory, @PluginName String pluginName, SitePaths site) {
- Config cfg = pluginConfigFactory.getGlobalPluginConfig(pluginName);
+ Configuration(SitePaths sitePaths) {
+ this(getConfigFile(sitePaths, PLUGIN_CONFIG_FILE), sitePaths);
+ }
+
+ @VisibleForTesting
+ Configuration(Config cfg, SitePaths site) {
main = new Main(site, cfg);
autoReindex = new AutoReindex(cfg);
peerInfo = new PeerInfo(cfg);
@@ -100,6 +109,20 @@
index = new Index(cfg);
websession = new Websession(cfg);
healthCheck = new HealthCheck(cfg);
+ sharedRefDb = new SharedRefDbConfiguration(cfg);
+ }
+
+ private static FileBasedConfig getConfigFile(SitePaths sitePaths, String configFileName) {
+ FileBasedConfig cfg =
+ new FileBasedConfig(sitePaths.etc_dir.resolve(configFileName).toFile(), FS.DETECTED);
+ String fileConfigFileName = cfg.getFile().getPath();
+ try {
+ log.atInfo().log("Loading configuration from {}", fileConfigFileName);
+ cfg.load();
+ } catch (IOException | ConfigInvalidException e) {
+ log.atSevere().withCause(e).log("Unable to load configuration from " + fileConfigFileName);
+ }
+ return cfg;
}
public Main main() {
@@ -150,6 +173,10 @@
return healthCheck;
}
+ public SharedRefDbConfiguration sharedRefDb() {
+ return sharedRefDb;
+ }
+
private static int getInt(Config cfg, String section, String name, int defaultValue) {
try {
return cfg.getInt(section, name, defaultValue);
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/Module.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/Module.java
index 744fac9..ddc294b 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/Module.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/Module.java
@@ -21,7 +21,7 @@
import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.RestForwarderModule;
import com.ericsson.gerrit.plugins.highavailability.index.IndexModule;
import com.ericsson.gerrit.plugins.highavailability.peers.PeerInfoModule;
-import com.google.inject.AbstractModule;
+import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.inject.Inject;
import com.google.inject.Provides;
import com.google.inject.Singleton;
@@ -29,7 +29,7 @@
import java.nio.file.Files;
import java.nio.file.Path;
-class Module extends AbstractModule {
+class Module extends LifecycleModule {
private final Configuration config;
@Inject
@@ -55,6 +55,10 @@
install(new AutoReindexModule());
}
install(new PeerInfoModule(config.peerInfo().strategy()));
+
+ if (config.sharedRefDb().getSharedRefDb().isEnabled()) {
+ listener().to(PluginStartup.class);
+ }
}
@Provides
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/PluginStartup.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/PluginStartup.java
new file mode 100644
index 0000000..5c19eec
--- /dev/null
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/PluginStartup.java
@@ -0,0 +1,45 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.ericsson.gerrit.plugins.highavailability;
+
+import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDatabaseWrapper;
+import com.google.gerrit.extensions.events.LifecycleListener;
+import com.google.inject.Inject;
+import com.google.inject.Injector;
+
+/**
+ * Purpose of this class is to copy SharedRefDatabaseWrapper instance from DB injector to plugin
+ * injector. This allows to bind different global ref-db implementations.
+ */
+public class PluginStartup implements LifecycleListener {
+ private SharedRefDatabaseWrapper sharedRefDb;
+ private Injector injector;
+
+ @Inject
+ public PluginStartup(SharedRefDatabaseWrapper sharedRefDb, Injector injector) {
+ this.sharedRefDb = sharedRefDb;
+ this.injector = injector;
+ }
+
+ @Override
+ public void start() {
+ injector.injectMembers(sharedRefDb);
+ }
+
+ @Override
+ public void stop() {
+ // Nothing to do
+ }
+}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java
new file mode 100644
index 0000000..74db7d2
--- /dev/null
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java
@@ -0,0 +1,70 @@
+// Copyright (C) 2020 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.ericsson.gerrit.plugins.highavailability;
+
+import com.gerritforge.gerrit.globalrefdb.validation.BatchRefUpdateValidator;
+import com.gerritforge.gerrit.globalrefdb.validation.LockWrapper;
+import com.gerritforge.gerrit.globalrefdb.validation.Log4jSharedRefLogger;
+import com.gerritforge.gerrit.globalrefdb.validation.RefUpdateValidator;
+import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDatabaseWrapper;
+import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDbBatchRefUpdate;
+import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDbConfiguration;
+import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDbGitRepositoryManager;
+import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDbRefDatabase;
+import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDbRefUpdate;
+import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDbRepository;
+import com.gerritforge.gerrit.globalrefdb.validation.SharedRefLogger;
+import com.gerritforge.gerrit.globalrefdb.validation.dfsrefdb.CustomSharedRefEnforcementByProject;
+import com.gerritforge.gerrit.globalrefdb.validation.dfsrefdb.DefaultSharedRefEnforcement;
+import com.gerritforge.gerrit.globalrefdb.validation.dfsrefdb.SharedRefEnforcement;
+import com.google.gerrit.extensions.config.FactoryModule;
+import com.google.gerrit.server.git.GitRepositoryManager;
+import com.google.inject.Inject;
+import com.google.inject.Scopes;
+
+public class ValidationModule extends FactoryModule {
+ final Configuration configuration;
+
+ @Inject
+ public ValidationModule(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
+ @Override
+ protected void configure() {
+ factory(SharedRefDbRepository.Factory.class);
+ factory(SharedRefDbRefDatabase.Factory.class);
+ factory(SharedRefDbRefUpdate.Factory.class);
+ factory(SharedRefDbBatchRefUpdate.Factory.class);
+ factory(RefUpdateValidator.Factory.class);
+ factory(BatchRefUpdateValidator.Factory.class);
+
+ bind(SharedRefDbConfiguration.class).toInstance(configuration.sharedRefDb());
+
+ bind(SharedRefDatabaseWrapper.class).in(Scopes.SINGLETON);
+ bind(SharedRefLogger.class).to(Log4jSharedRefLogger.class);
+ factory(LockWrapper.Factory.class);
+
+ bind(GitRepositoryManager.class).to(SharedRefDbGitRepositoryManager.class);
+
+ if (configuration.sharedRefDb().getSharedRefDb().getEnforcementRules().isEmpty()) {
+ bind(SharedRefEnforcement.class).to(DefaultSharedRefEnforcement.class).in(Scopes.SINGLETON);
+ } else {
+ bind(SharedRefEnforcement.class)
+ .to(CustomSharedRefEnforcementByProject.class)
+ .in(Scopes.SINGLETON);
+ }
+ }
+}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/GroupReindexRunnable.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/GroupReindexRunnable.java
index e37234c..1d31ebc 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/GroupReindexRunnable.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/autoreindex/GroupReindexRunnable.java
@@ -15,7 +15,7 @@
package com.ericsson.gerrit.plugins.highavailability.autoreindex;
import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.AbstractIndexRestApiServlet;
-import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.entities.GroupReference;
import com.google.gerrit.server.group.db.Groups;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.inject.Inject;
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ChangeCheckerImpl.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ChangeCheckerImpl.java
index fe04ee9..6587acf 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ChangeCheckerImpl.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ChangeCheckerImpl.java
@@ -17,7 +17,7 @@
import com.ericsson.gerrit.plugins.highavailability.forwarder.IndexEvent;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Comment;
+import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.ChangeFinder;
import com.google.gerrit.server.git.GitRepositoryManager;
@@ -144,7 +144,7 @@
private long getTsFromChangeAndDraftComments(ChangeNotes notes) {
Change change = notes.getChange();
Timestamp changeTs = change.getLastUpdatedOn();
- for (Comment comment : commentsUtil.draftByChange(changeNotes.get())) {
+ for (HumanComment comment : commentsUtil.draftByChange(changeNotes.get())) {
Timestamp commentTs = comment.writtenOn;
changeTs = commentTs.after(changeTs) ? commentTs : changeTs;
}
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index fd0b56e..851f584 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -7,10 +7,10 @@
* sharing the git repositories using a shared file system (e.g. NFS)
* behind a load balancer (e.g. HAProxy)
-Currently, the mode supported is one active instance and multiple backup
-(passive) instances but eventually the plan is to support `n` active instances.
-In the active/passive mode, the active instance is handling all traffic while
-the passives are kept updated to be always ready to take over.
+Default mode is one active instance and multiple backup (passive) instances
+but `n` active instances can be configured. In the active/passive mode, the active
+instance is handling all traffic while the passives are kept updated to be always
+ready to take over.
Even if git repositories are shared by the instances, there are a few areas
of concern in order to be able to switch traffic between instances in a
@@ -46,7 +46,7 @@
The built-in Gerrit H2 based web session cache is replaced with a file based
implementation that is shared amongst the instances.
-## Setup
+## Active/passive setup
Prerequisites:
@@ -103,3 +103,72 @@
For further information and supported options, refer to [config](config.md)
documentation.
+
+## Active/active setup
+
+Prerequisites:
+
+* Git repositories must be located on a shared file system
+* A directory on a shared file system must be available for @PLUGIN@ to use
+* An implementation of global-refdb (e.g. Zookeeper) must be accessible from all the active
+instances
+
+For the instances:
+
+* Configure gerrit.basePath in gerrit.config to the shared repositories location
+* Configure gerrit.serverId in gerrit.config based on [config](config.md)'s introduction
+* Install and configure this @PLUGIN@ plugin [further](config.md) or based on example
+configuration
+* Install @PLUGIN@ plugin as a database module in $GERRIT_SITE/lib(please note that
+@PLUGIN plugin must be installed as a plugin and as a database module) and add
+`installDbModule = com.ericsson.gerrit.plugins.highavailability.ValidationModule`
+to the gerrit section in gerrit.config
+* Install [global-refdb library](https://mvnrepository.com/artifact/com.gerritforge/global-refdb) as a library module in $GERRIT_SITE/lib and add
+`installModule = com.gerritforge.gerrit.globalrefdb.validation.LibModule` to the gerrit
+section in gerrit.config
+* Install and configure [zookeeper-refdb plugin](https://gerrit-ci.gerritforge.com/view/Plugins-master/job/plugin-zookeeper-refdb-bazel-master) based on [config.md](https://gerrit.googlesource.com/plugins/zookeeper-refdb/+/refs/heads/master/src/main/resources/Documentation/config.md)
+* Configure ref-database.enabled = true in @PLUGIN@.config to enable validation with
+global-refdb.
+
+Here is an example of the minimal @PLUGIN@.config:
+
+Active instance one
+
+```
+[main]
+ sharedDirectory = /directory/accessible/from/both/instances
+
+[peerInfo "static"]
+ url = http://backupNodeHost1:8081/
+
+[http]
+ user = username
+ password = password
+
+[ref-database]
+ enabled = true
+```
+
+Active instance two
+
+```
+[main]
+ sharedDirectory = /directory/accessible/from/both/instances
+
+[peerInfo "static"]
+ url = http://primaryNodeHost:8080/
+
+[http]
+ user = username
+ password = password
+
+[ref-database]
+ enabled = true
+```
+
+Minimal zookeeper-refdb.config for both active instances:
+
+```
+[ref-database "zookeeper"]
+ connectString = zookeeperhost:2181
+```
\ No newline at end of file
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index f711fe3..2976de5 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -235,6 +235,32 @@
```healthcheck.enable```
: Whether to enable the health check endpoint. Defaults to 'true'.
+```ref-database.enabled```
+: Enable the use of a global ref-database. Defaults to 'false'.
+
+```ref-database.enforcementRules.<policy>```
+: Level of consistency enforcement across sites on a project:refs basis.
+ Supports two values for enforcing the policy on multiple projects or refs.
+ If the project or ref is omitted, apply the policy to all projects or all refs.
+
+ The <policy> can be one of the following values:
+
+ 1. REQUIRED - Throw an exception if a git ref-update is processed against
+ a local ref not yet in sync with the global ref-database.
+ The user transaction is cancelled. LOCK_FAILURE is reported upstream.
+
+ 2. IGNORED - Do not validate against the global ref-database.
+
+ *Example:*
+ ```
+ [ref-database "enforcementRules"]
+ IGNORED = AProject:/refs/heads/feature
+ ```
+
+ Ignore the alignment with the global ref-db for AProject on refs/heads/feature.
+
+ Defaults to no rule. All projects are REQUIRED to be consistent on all refs.
+
File 'gerrit.config'
--------------------
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/ConfigurationTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/ConfigurationTest.java
index a9537bd..4bfac28 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/ConfigurationTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/ConfigurationTest.java
@@ -62,7 +62,6 @@
import static com.google.common.truth.Truth8.assertThat;
import static java.util.concurrent.TimeUnit.SECONDS;
import static org.junit.Assert.assertEquals;
-import static org.mockito.Mockito.when;
import com.ericsson.gerrit.plugins.highavailability.Configuration.PeerInfoStrategy;
import com.google.common.collect.ImmutableList;
@@ -104,12 +103,11 @@
@Before
public void setUp() throws IOException {
globalPluginConfig = new Config();
- when(pluginConfigFactoryMock.getGlobalPluginConfig(PLUGIN_NAME)).thenReturn(globalPluginConfig);
sitePaths = new SitePaths(SITE_PATH);
}
private Configuration getConfiguration() {
- return new Configuration(pluginConfigFactoryMock, PLUGIN_NAME, sitePaths);
+ return new Configuration(globalPluginConfig, sitePaths);
}
@Test
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/AbstractIndexForwardingIT.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/AbstractIndexForwardingIT.java
index 5843908..83f86d0 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/AbstractIndexForwardingIT.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/AbstractIndexForwardingIT.java
@@ -25,15 +25,19 @@
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
import static com.google.common.truth.Truth.assertThat;
+import com.ericsson.gerrit.plugins.highavailability.Configuration;
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.TestPlugin;
import com.google.gerrit.acceptance.UseLocalDisk;
-import com.google.gerrit.acceptance.config.GlobalPluginConfig;
+import com.google.gerrit.server.config.SitePaths;
+import com.google.inject.Inject;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.apache.http.HttpStatus;
+import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.util.FS;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
@@ -50,17 +54,23 @@
@Rule public WireMockRule wireMockRule = new WireMockRule(options().port(PORT));
+ @Inject SitePaths sitePaths;
+
@Override
public void setUpTestPlugin() throws Exception {
givenThat(any(anyUrl()).willReturn(aResponse().withStatus(HttpStatus.SC_NO_CONTENT)));
+ FileBasedConfig fileBasedConfig =
+ new FileBasedConfig(
+ sitePaths.etc_dir.resolve(Configuration.PLUGIN_CONFIG_FILE).toFile(), FS.DETECTED);
+ fileBasedConfig.setString("peerInfo", "static", "url", URL);
+ fileBasedConfig.setInt("http", null, "retryInterval", 100);
+ fileBasedConfig.save();
beforeAction();
super.setUpTestPlugin();
}
@Test
@UseLocalDisk
- @GlobalPluginConfig(pluginName = "high-availability", name = "peerInfo.static.url", value = URL)
- @GlobalPluginConfig(pluginName = "high-availability", name = "http.retryInterval", value = "100")
public void testIndexForwarding() throws Exception {
String expectedRequest = getExpectedRequest();
CountDownLatch expectedRequestLatch = new CountDownLatch(1);