Merge branch 'stable-3.12'

* stable-3.12:
  Update base OS to AlmaLinux 9.3 and Java 17
  Get global-refdb.jar from Gerrit-CI
  Bump Gerrit to 3.9
  Add missing syslog-sidecar in docker-compose.yaml
  Removing obsolete version attribute in docker-compose.yaml
  Active/active setup using zookeeper-refdb plugin and zookeeper service

Change-Id: Ibe9e2dcf387705b3252c90916ab4285e0131dff6
diff --git a/BUILD b/BUILD
index 3735cb3..4beff6e 100644
--- a/BUILD
+++ b/BUILD
@@ -21,7 +21,6 @@
     resources = glob(["src/main/resources/**/*"]),
     deps = [
         ":global-refdb-neverlink",
-        "@auto-value//jar",
         "@failsafe//jar",
         "@jgroups-kubernetes//jar",
         "@jgroups//jar",
diff --git a/README.md b/README.md
index fcf0566..11a33b2 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
 # Gerrit high-availability plugin
 
-This plugin allows deploying a cluster of multiple Gerrit primaries
-on the same data-center sharing the same Git repositories.
+This plugin allows deploying a cluster of multiple Gerrit primary servers
+in the same data-center sharing the same Git repositories.
 
 Requirements for the Gerrit primaries are:
 
@@ -17,6 +17,18 @@
 
 Refer to the [build instructions in the plugin documentation](src/main/resources/Documentation/build.md).
 
+## Installation
+
+Install
+
+- the `high-availability` plugin in the Gerrit site's `plugins` folder.
+
+> **NOTE** the `global-refdb` lib module in the Gerrit site's `lib` folder, even if it is not used or referenced as libModule in the `gerrit.config`, because of a bug in the high-availability plugin initialisation sequence.
+
+In active-active deployments with multiple Gerrit primaries, installation of a global-refdb
+implementation is needed to maintain consistent ref updates across all
+Gerrit primary sites.
+
 ## Sample configuration for two Gerrit primaries in high-availability
 
 Assuming that the Gerrit primaries in the clusters are `gerrit-01.mycompany.com` and
@@ -76,7 +88,11 @@
 
 It is the simplest and safest configuration, where only one Gerrit primary at a
 time serves the incoming requests.
+<<<<<<< HEAD
+In case of failure of the active primary, the traffic is forwarded to the backup.
+=======
 In case of failure of the primary, the traffic is forwarded to the backup.
+>>>>>>> stable-3.12
 
 Assuming a load-balancing implemented using [HAProxy](http://www.haproxy.org/)
 associated with the domain name `gerrit.mycompany.com`, exposing Gerrit cluster nodes
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java
index 9229d01..c770092 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/ValidationModule.java
@@ -26,9 +26,6 @@
 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.extensions.registration.DynamicSet;
 import com.google.gerrit.server.ExceptionHook;
@@ -60,14 +57,6 @@
 
     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);
-    }
-
     DynamicSet.bind(binder(), ExceptionHook.class).to(SharedRefDbExceptionHook.class);
   }
 }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/peers/jgroups/JGroupsPeerInfoProvider.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/peers/jgroups/JGroupsPeerInfoProvider.java
index 63f65d6..6079804 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/peers/jgroups/JGroupsPeerInfoProvider.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/peers/jgroups/JGroupsPeerInfoProvider.java
@@ -14,10 +14,10 @@
 
 package com.ericsson.gerrit.plugins.highavailability.peers.jgroups;
 
-import autovalue.shaded.com.google.common.collect.ImmutableMap;
 import com.ericsson.gerrit.plugins.highavailability.Configuration;
 import com.ericsson.gerrit.plugins.highavailability.peers.PeerInfo;
 import com.google.common.annotations.VisibleForTesting;
+import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.flogger.FluentLogger;
 import com.google.gerrit.extensions.events.LifecycleListener;
diff --git a/src/main/resources/Documentation/about.md b/src/main/resources/Documentation/about.md
index 6fcd2e2..f62c035 100644
--- a/src/main/resources/Documentation/about.md
+++ b/src/main/resources/Documentation/about.md
@@ -27,15 +27,18 @@
 sharing or synchronizing them.
 
 #### Caches
+
 Every time a cache eviction occurs in one of the instances, the eviction will be
 forwarded the other nodes so their caches do not contain stale entries.
 
 #### Secondary indexes
+
 Every time the secondary index is modified in one of the instances, e.g., a change
 is added, updated or removed from the index, the others instances index are updated
 accordingly. This way, both indexes are kept synchronized.
 
 #### Stream events
+
 Every time a stream event occurs in one of the instances
 (see [more events info](https://gerrit-review.googlesource.com/Documentation/cmd-stream-events.html#events)),
 the event is forwarded to the other instances which re-plays it. This way, the output
@@ -43,6 +46,7 @@
 connected to.
 
 #### Web session
+
 The built-in Gerrit H2 based web session cache is replaced with a file based
 implementation that is shared amongst the instances.
 
@@ -55,8 +59,8 @@
 
 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
+* 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 below.
 
 Here is an example of the minimal @PLUGIN@.config:
@@ -110,25 +114,34 @@
 
 * 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
+* An implementation of `global-refdb` (e.g. Zookeeper) must be accessible from all the active
+  instances to maintain consistent ref updates across all Gerrit primary sites
+
+The following `global-refdb` implementations are available:
+
+* [zookeeper-refdb plugin](https://gerrit.googlesource.com/plugins/zookeeper-refdb/+/refs/heads/master)
+  using Apache Zookeeper
+* [aws-dynamodb-refdb plugin](https://gerrit.googlesource.com/plugins/aws-dynamodb-refdb/+/refs/heads/master)
+  using AWS DynamoDB
+* [spanner-refdb plugin](https://gerrit.googlesource.com/plugins/spanner-refdb/+/refs/heads/master)
+  using Google Cloud Spanner
 
 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
+* 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 @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 <br/>
+`installDbModule = com.ericsson.gerrit.plugins.highavailability.ValidationModule` <br/>
+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  <br/>
+`installModule = com.gerritforge.gerrit.globalrefdb.validation.LibModule` <br/>
+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.
+* Configure `ref-database.enabled = true` in @PLUGIN@.config to enable validation with
+`global-refdb`.
 
 Here is an example of the minimal @PLUGIN@.config:
 
@@ -166,12 +179,13 @@
   enabled = true
 ```
 
-Minimal zookeeper-refdb.config for both active instances:
+Minimal `zookeeper-refdb.config` for both active instances:
 
 ```
 [ref-database "zookeeper"]
   connectString = zookeeperhost:2181
 ```
+
 ### Last index update timestamp storage
 
 The plugin keeps track of the timestamp when it lastly updated an index.
@@ -180,6 +194,7 @@
 sync with the primary, for example, after a node being offline for a long time.
 
 The HA plugin keeps the last update timestamp for each index in the following files:
+
 * `<gerrit_home>/data/high-availability/account`
 * `<gerrit_home>/data/high-availability/change`
 
diff --git a/src/test/README.md b/src/test/README.md
index 80fe2e4..b0aa3c4 100644
--- a/src/test/README.md
+++ b/src/test/README.md
@@ -1,8 +1,8 @@
 # Gerrit high-availability docker setup example
 
 The Docker Compose project in the docker directory contains a simple test
-environment of two Gerrit primaries in HA configuration, with their git repos
-hosted on NFS filesystem.
+environment of two Gerrit primary servers in HA configuration, with their
+git repos hosted on NFS filesystem.
 
 ## How to build
 
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 b51e1a0..0fb7dad 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/ConfigurationTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/ConfigurationTest.java
@@ -217,9 +217,6 @@
 
     globalPluginConfig.setInt(HTTP_SECTION, null, CONNECTION_TIMEOUT_KEY, TIMEOUT);
     assertThat(getConfiguration().http().connectionTimeout().toMillis()).isEqualTo(TIMEOUT);
-
-    globalPluginConfig.setString(HTTP_SECTION, null, CONNECTION_TIMEOUT_KEY, INVALID_INT);
-    assertThat(getConfiguration().http().connectionTimeout()).isEqualTo(DEFAULT_TIMEOUT);
   }
 
   @Test
@@ -228,9 +225,6 @@
 
     globalPluginConfig.setInt(HTTP_SECTION, null, SOCKET_TIMEOUT_KEY, TIMEOUT);
     assertThat(getConfiguration().http().socketTimeout().toMillis()).isEqualTo(TIMEOUT);
-
-    globalPluginConfig.setString(HTTP_SECTION, null, SOCKET_TIMEOUT_KEY, INVALID_INT);
-    assertThat(getConfiguration().http().socketTimeout()).isEqualTo(DEFAULT_TIMEOUT);
   }
 
   @Test
@@ -256,9 +250,6 @@
 
     globalPluginConfig.setInt(HTTP_SECTION, null, RETRY_INTERVAL_KEY, RETRY_INTERVAL);
     assertThat(getConfiguration().http().retryInterval().toMillis()).isEqualTo(RETRY_INTERVAL);
-
-    globalPluginConfig.setString(HTTP_SECTION, null, RETRY_INTERVAL_KEY, INVALID_INT);
-    assertThat(getConfiguration().http().retryInterval()).isEqualTo(DEFAULT_RETRY_INTERVAL);
   }
 
   @Test