Merge branch 'stable-3.4' into stable-3.5

* stable-3.4:
  Remove redundant format calls in log calls
  Add put method to create/update global-refdb entry
  Add happy path test for BatchRefUpdateValidator
  Remove Maven legacy pom.xml
  Return immediately if local ref update fails
  Remove references to Zookeeper in logs
  Squash filter/findFirst/isPresent into anyMatch
  Fix typo in private method

Change-Id: I67f40a5bd8fd8c6ad685c9706dd3ee7a13afd7d3
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index 9b22b88..0000000
--- a/pom.xml
+++ /dev/null
@@ -1,168 +0,0 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <modelVersion>4.0.0</modelVersion>
-
-    <groupId>com.gerritforge</groupId>
-    <artifactId>global-refdb</artifactId>
-    <version>3.5.6</version>
-    <packaging>jar</packaging>
-
-    <name>global-refdb</name>
-    <description>Global ref-database for use with Gerrit Code Review</description>
-    <url>https://github.com/gerritforge/global-refdb</url>
-
-    <licenses>
-        <license>
-            <name>The Apache Software License, Version 2.0</name>
-            <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
-            <distribution>repo</distribution>
-        </license>
-    </licenses>
-
-    <scm>
-        <url>https://review.gerrithub.io/GerritForge/global-refdb.git</url>
-        <connection>https://review.gerrithub.io/GerritForge/global-refdb.git</connection>
-    </scm>
-
-    <developers>
-        <developer>
-            <name>Luca Milanesio</name>
-        </developer>
-        <developer>
-            <name>Marcin Czech</name>
-        </developer>
-        <developer>
-            <name>Antonio Barone</name>
-        </developer>
-    </developers>
-
-    <properties>
-        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-        <gerrit.version>3.5.6</gerrit.version>
-    </properties>
-
-    <dependencies>
-        <dependency>
-            <groupId>com.google.gerrit</groupId>
-            <artifactId>gerrit-plugin-api</artifactId>
-            <version>${gerrit.version}</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.ryanharter.auto.value</groupId>
-            <artifactId>auto-value-gson</artifactId>
-            <version>1.3.0</version>
-            <scope>provided</scope>
-        </dependency>
-        <dependency>
-            <groupId>com.google.gerrit</groupId>
-            <artifactId>gerrit-acceptance-framework</artifactId>
-            <version>${gerrit.version}</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.bouncycastle</groupId>
-            <artifactId>bcprov-jdk15on</artifactId>
-            <version>1.61</version>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>junit</groupId>
-            <artifactId>junit</artifactId>
-            <version>4.12</version>
-            <scope>test</scope>
-        </dependency>
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-compiler-plugin</artifactId>
-                <version>3.6.1</version>
-                <configuration>
-                    <source>1.8</source>
-                    <target>11</target>
-                </configuration>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-source-plugin</artifactId>
-                <version>3.1.0</version>
-                <executions>
-                    <execution>
-                        <id>attach-sources</id>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-javadoc-plugin</artifactId>
-                <version>3.2.0</version>
-                <executions>
-                    <execution>
-                        <id>attach-javadocs</id>
-                        <goals>
-                            <goal>jar</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-release-plugin</artifactId>
-                <version>2.5.3</version>
-            </plugin>
-            <plugin>
-                <groupId>org.apache.maven.plugins</groupId>
-                <artifactId>maven-gpg-plugin</artifactId>
-                <version>1.6</version>
-                <executions>
-                    <execution>
-                        <id>sign-artifacts</id>
-                        <phase>verify</phase>
-                        <goals>
-                            <goal>sign</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>
-                <groupId>com.theoryinpractise</groupId>
-                <artifactId>googleformatter-maven-plugin</artifactId>
-                <version>1.7.3</version>
-                <executions>
-                    <execution>
-                        <id>reformat-sources</id>
-                        <configuration>
-                            <includeStale>false</includeStale>
-                            <style>GOOGLE</style>
-                            <formatMain>true</formatMain>
-                            <formatTest>true</formatTest>
-                            <filterModified>false</filterModified>
-                            <skip>false</skip>
-                            <fixImports>true</fixImports>
-                            <maxLineLength>100</maxLineLength>
-                        </configuration>
-                        <goals>
-                            <goal>format</goal>
-                        </goals>
-                        <phase>process-sources</phase>
-                    </execution>
-                </executions>
-            </plugin>
-        </plugins>
-    </build>
-
-    <distributionManagement>
-        <repository>
-            <id>sonatype-nexus-staging</id>
-            <name>Sonatype Nexus Staging</name>
-            <url>https://oss.sonatype.org/service/local/staging/deploy/maven2</url>
-        </repository>
-    </distributionManagement>
-</project>
-
diff --git a/src/main/java/com/gerritforge/gerrit/globalrefdb/ExtendedGlobalRefDatabase.java b/src/main/java/com/gerritforge/gerrit/globalrefdb/ExtendedGlobalRefDatabase.java
new file mode 100644
index 0000000..c6f8de7
--- /dev/null
+++ b/src/main/java/com/gerritforge/gerrit/globalrefdb/ExtendedGlobalRefDatabase.java
@@ -0,0 +1,33 @@
+// Copyright (C) 2023 GerritForge Ltd
+//
+// 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.gerritforge.gerrit.globalrefdb;
+
+import com.google.gerrit.entities.Project;
+
+public interface ExtendedGlobalRefDatabase extends GlobalRefDatabase {
+
+  /**
+   * Set a value of generic type T.
+   *
+   * <p>Set is executed as an atomic operation.
+   *
+   * @param project project name of the ref.
+   * @param refName to store the value for.
+   * @param newValue new value to store.
+   * @param <T> Type of the current and new value
+   * @throws GlobalRefDbSystemError the reference cannot be set due to a system error.
+   */
+  <T> void put(Project.NameKey project, String refName, T newValue) throws GlobalRefDbSystemError;
+}
diff --git a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidator.java b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidator.java
index 22aae61..f461a9a 100644
--- a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidator.java
+++ b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidator.java
@@ -140,7 +140,7 @@
       return;
     }
 
-    List<RefPair> refsToUpdate = getRefsPairs(commands).collect(Collectors.toList());
+    List<RefPair> refsToUpdate = getRefPairs(commands).collect(Collectors.toList());
     List<RefPair> refsFailures =
         refsToUpdate.stream().filter(RefPair::hasFailed).collect(Collectors.toList());
     if (!refsFailures.isEmpty()) {
@@ -195,10 +195,7 @@
 
   private void updateSharedRefDb(Stream<ReceiveCommand> commandStream, List<RefPair> refsToUpdate)
       throws IOException {
-    if (commandStream
-        .filter(cmd -> cmd.getResult() != ReceiveCommand.Result.OK)
-        .findFirst()
-        .isPresent()) {
+    if (commandStream.anyMatch(cmd -> cmd.getResult() != ReceiveCommand.Result.OK)) {
       return;
     }
 
@@ -207,7 +204,7 @@
     }
   }
 
-  private Stream<RefPair> getRefsPairs(List<ReceiveCommand> receivedCommands) {
+  private Stream<RefPair> getRefPairs(List<ReceiveCommand> receivedCommands) {
     return receivedCommands.stream().map(this::getRefPairForCommand);
   }
 
diff --git a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/Log4jSharedRefLogger.java b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/Log4jSharedRefLogger.java
index 3b4dbb2..04ffeed 100644
--- a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/Log4jSharedRefLogger.java
+++ b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/Log4jSharedRefLogger.java
@@ -140,6 +140,18 @@
     }
   }
 
+  @Override
+  public <T> void logRefUpdate(String project, String refName, T newRefValue) {
+    if (newRefValue != null) {
+      sharedRefDBLog.info(
+          gson.toJson(
+              new SharedRefLogEntry.UpdateRef(
+                  project, refName, null, safeToString(newRefValue), null, null)));
+    } else {
+      sharedRefDBLog.info(gson.toJson(new SharedRefLogEntry.DeleteRef(project, refName, null)));
+    }
+  }
+
   /**
    * {@inheritDoc}.
    *
diff --git a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/RefUpdateValidator.java b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/RefUpdateValidator.java
index c86a346..85e803a 100644
--- a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/RefUpdateValidator.java
+++ b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/RefUpdateValidator.java
@@ -189,10 +189,11 @@
       RefPair refPairForUpdate = newRefPairFrom(refUpdate);
       compareAndGetLatestLocalRef(refPairForUpdate, locks);
       RefUpdate.Result result = refUpdateFunction.invoke();
+      if (!isSuccessful(result)) {
+        return result;
+      }
       try {
-        if (isSuccessful(result)) {
-          updateSharedDbOrThrowExceptionFor(refPairForUpdate);
-        }
+        updateSharedDbOrThrowExceptionFor(refPairForUpdate);
       } catch (Exception e) {
         result = rollbackFunction.invoke(refPairForUpdate.compareRef.getObjectId());
         if (isSuccessful(result)) {
@@ -219,9 +220,9 @@
 
     String errorMessage =
         String.format(
-            "Not able to persist the data in Zookeeper for project '%s' and ref '%s',"
+            "Not able to persist the data in SharedRef for project '%s' and ref '%s',"
                 + "the cluster is now in Split Brain since the commit has been "
-                + "persisted locally but not in SharedRef the value %s",
+                + "persisted locally but not in global-refdb the value %s",
             projectName, refPair.getName(), refPair.putValue);
     boolean succeeded;
     try {
@@ -230,7 +231,7 @@
               Project.nameKey(projectName), refPair.compareRef, refPair.putValue);
     } catch (GlobalRefDbSystemError e) {
       logger.atWarning().withCause(e).log(
-          "Not able to persist the data in Zookeeper for project '%s' and ref '%s', message: %s",
+          "Not able to persist the data in global-refdb for project '%s' and ref '%s', message: %s",
           projectName, refPair.getName(), e.getMessage());
       throw e;
     }
@@ -343,7 +344,7 @@
                   logger.atSevere().withCause(closingException).log(
                       "Exception trying to release resource %s, "
                           + "the locked resources won't be accessible in all cluster unless"
-                          + " the lock is removed from ZK manually",
+                          + " the lock is removed from global-refdb manually",
                       closeable);
                 }
               });
diff --git a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefDBMetrics.java b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefDBMetrics.java
index ff483ab..c907831 100644
--- a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefDBMetrics.java
+++ b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefDBMetrics.java
@@ -28,6 +28,7 @@
   private final Timer0 getOperationExecutionTime;
   private final Timer0 existsExecutionTime;
   private Timer0 compareAndPutExecutionTime;
+  private Timer0 setExecutionTime;
   private Timer0 removeExecutionTime;
   private Timer0 isUpToDateExecutionTime;
 
@@ -39,6 +40,12 @@
             new Description("Time spent on compareAndPut.")
                 .setCumulative()
                 .setUnit(Description.Units.MILLISECONDS));
+    setExecutionTime =
+        metricMaker.newTimer(
+            "global_refdb/set_latency",
+            new Description("Time spent on set.")
+                .setCumulative()
+                .setUnit(Description.Units.MILLISECONDS));
     getOperationExecutionTime =
         metricMaker.newTimer(
             "global_refdb/get_latency",
@@ -76,6 +83,10 @@
     return compareAndPutExecutionTime.start();
   }
 
+  public Context startSetExecutionTime() {
+    return setExecutionTime.start();
+  }
+
   public Context startGetExecutionTime() {
     return getOperationExecutionTime.start();
   }
diff --git a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefDatabaseWrapper.java b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefDatabaseWrapper.java
index c3b41e8..c9a6c7d 100644
--- a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefDatabaseWrapper.java
+++ b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefDatabaseWrapper.java
@@ -14,6 +14,7 @@
 
 package com.gerritforge.gerrit.globalrefdb.validation;
 
+import com.gerritforge.gerrit.globalrefdb.ExtendedGlobalRefDatabase;
 import com.gerritforge.gerrit.globalrefdb.GlobalRefDatabase;
 import com.gerritforge.gerrit.globalrefdb.GlobalRefDbLockException;
 import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError;
@@ -35,7 +36,7 @@
  * {@link NoopSharedRefDatabase} instance is wrapped instead.
  */
 @Singleton
-public class SharedRefDatabaseWrapper implements GlobalRefDatabase {
+public class SharedRefDatabaseWrapper implements ExtendedGlobalRefDatabase {
   private static final FluentLogger log = FluentLogger.forEnclosingClass();
   private static final GlobalRefDatabase NOOP_REFDB = new NoopSharedRefDatabase();
 
@@ -99,6 +100,23 @@
     }
   }
 
+  @Override
+  public <T> void put(Project.NameKey project, String refName, T newValue)
+      throws GlobalRefDbSystemError {
+    if (!isSetOperationSupported()) {
+      throw new UnsupportedOperationException(
+          "GlobalRefDb implementation doesn't support set operation");
+    }
+    try (Context context = metrics.startSetExecutionTime()) {
+      ((ExtendedGlobalRefDatabase) sharedRefDb()).put(project, refName, newValue);
+      sharedRefLogger.logRefUpdate(project.get(), refName, newValue);
+    }
+  }
+
+  public boolean isSetOperationSupported() {
+    return sharedRefDb() instanceof ExtendedGlobalRefDatabase;
+  }
+
   /** {@inheritDoc}. The operation is logged. */
   @Override
   public AutoCloseable lockRef(Project.NameKey project, String refName)
diff --git a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefLogEntry.java b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefLogEntry.java
index c72ab7c..4b8132f 100644
--- a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefLogEntry.java
+++ b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefLogEntry.java
@@ -41,7 +41,7 @@
     UpdateRef(
         String projectName,
         String refName,
-        String oldId,
+        @Nullable String oldId,
         String newId,
         @Nullable GitPerson committer,
         @Nullable String comment) {
@@ -68,7 +68,7 @@
     public String refName;
     public String oldId;
 
-    DeleteRef(String projectName, String refName, String oldId) {
+    DeleteRef(String projectName, String refName, @Nullable String oldId) {
       this.type = Type.DELETE_REF;
       this.projectName = projectName;
       this.refName = refName;
diff --git a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefLogger.java b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefLogger.java
index 858ba18..f61f253 100644
--- a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefLogger.java
+++ b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/SharedRefLogger.java
@@ -42,6 +42,16 @@
   <T> void logRefUpdate(String project, String refName, T currRef, T newRefValue);
 
   /**
+   * Log the update of ref pointed to by refName, in project 'project' to ref 'newRefValue'
+   *
+   * @param project the project the update is for
+   * @param refName the name of the ref being updatex
+   * @param newRefValue the new value of the ref being updated
+   * @param <T> Type of the 'currRef' and the 'newRefValue'
+   */
+  <T> void logRefUpdate(String project, String refName, T newRefValue);
+
+  /**
    * Log the deletion of 'project' from the global refdb
    *
    * @param project the project being deleted
diff --git a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/dfsrefdb/NoopSharedRefDatabase.java b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/dfsrefdb/NoopSharedRefDatabase.java
index 960b311..1ce480a 100644
--- a/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/dfsrefdb/NoopSharedRefDatabase.java
+++ b/src/main/java/com/gerritforge/gerrit/globalrefdb/validation/dfsrefdb/NoopSharedRefDatabase.java
@@ -14,6 +14,7 @@
 
 package com.gerritforge.gerrit.globalrefdb.validation.dfsrefdb;
 
+import com.gerritforge.gerrit.globalrefdb.ExtendedGlobalRefDatabase;
 import com.gerritforge.gerrit.globalrefdb.GlobalRefDatabase;
 import com.gerritforge.gerrit.globalrefdb.GlobalRefDbLockException;
 import com.gerritforge.gerrit.globalrefdb.GlobalRefDbSystemError;
@@ -29,7 +30,7 @@
  * <p>This is useful for setting up a test environment and allows multi-site library to be installed
  * independently from any additional libModules or the existence of a specific Ref-DB installation.
  */
-public class NoopSharedRefDatabase implements GlobalRefDatabase {
+public class NoopSharedRefDatabase implements ExtendedGlobalRefDatabase {
 
   /**
    * Project/ref is always considered up-to-date
@@ -126,4 +127,10 @@
       throws GlobalRefDbSystemError {
     return Optional.empty();
   }
+
+  @Override
+  public <T> void put(Project.NameKey project, String refName, T newValue)
+      throws GlobalRefDbSystemError {
+    // do nothing
+  }
 }
diff --git a/src/test/java/com/gerritforge/gerrit/globalrefdb/ExtendedGlobalRefDatabaseTest.java b/src/test/java/com/gerritforge/gerrit/globalrefdb/ExtendedGlobalRefDatabaseTest.java
new file mode 100644
index 0000000..d58e0f3
--- /dev/null
+++ b/src/test/java/com/gerritforge/gerrit/globalrefdb/ExtendedGlobalRefDatabaseTest.java
@@ -0,0 +1,33 @@
+// Copyright (C) 2023 GerritForge Ltd
+//
+// 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.gerritforge.gerrit.globalrefdb;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import java.util.Optional;
+import org.junit.Test;
+
+public class ExtendedGlobalRefDatabaseTest extends GlobalRefDatabaseTest {
+
+  @Test
+  public void shouldSetLongValueInTheGlobalRefDB() {
+    objectUnderTest.put(project, refName, 1L);
+
+    Optional<Long> o = objectUnderTest.get(project, refName, Long.class);
+
+    assertThat(o.isPresent()).isTrue();
+    assertThat(o.get()).isEqualTo(1L);
+  }
+}
diff --git a/src/test/java/com/gerritforge/gerrit/globalrefdb/FakeGlobalRefDatabase.java b/src/test/java/com/gerritforge/gerrit/globalrefdb/FakeGlobalRefDatabase.java
index 44c4fbb..5d4175f 100644
--- a/src/test/java/com/gerritforge/gerrit/globalrefdb/FakeGlobalRefDatabase.java
+++ b/src/test/java/com/gerritforge/gerrit/globalrefdb/FakeGlobalRefDatabase.java
@@ -16,6 +16,7 @@
 
 import com.google.common.collect.MapMaker;
 import com.google.gerrit.entities.Project;
+import com.google.gerrit.entities.Project.NameKey;
 import java.util.Optional;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicReference;
@@ -26,7 +27,7 @@
 import org.junit.Ignore;
 
 @Ignore
-public class FakeGlobalRefDatabase implements GlobalRefDatabase {
+public class FakeGlobalRefDatabase implements ExtendedGlobalRefDatabase {
 
   private ConcurrentMap<Project.NameKey, ConcurrentMap<String, AtomicReference<ObjectId>>>
       keyValueStore;
@@ -132,6 +133,12 @@
     return projectRefLock;
   }
 
+  @Override
+  public <T> void put(NameKey project, String refName, T newValue) throws GlobalRefDbSystemError {
+    String key = String.format("%s/%s", project.get(), refName);
+    genericKeyValueStore.put(key, new AtomicReference<>(newValue));
+  }
+
   private static class RefLock implements AutoCloseable {
     private Lock lock;
 
diff --git a/src/test/java/com/gerritforge/gerrit/globalrefdb/GlobalRefDatabaseTest.java b/src/test/java/com/gerritforge/gerrit/globalrefdb/GlobalRefDatabaseTest.java
index bb5ad8d..8ed1f4c 100644
--- a/src/test/java/com/gerritforge/gerrit/globalrefdb/GlobalRefDatabaseTest.java
+++ b/src/test/java/com/gerritforge/gerrit/globalrefdb/GlobalRefDatabaseTest.java
@@ -31,7 +31,8 @@
 
 public class GlobalRefDatabaseTest extends AbstractDaemonTest {
 
-  private String refName = RefNames.REFS_HEADS + "branch";
+  protected ExtendedGlobalRefDatabase objectUnderTest;
+  protected String refName = RefNames.REFS_HEADS + "branch";
 
   private ObjectId objectId1;
   private ObjectId objectId2;
@@ -45,8 +46,6 @@
 
   private Executor executor = Executors.newFixedThreadPool(1);
 
-  private GlobalRefDatabase objectUnderTest;
-
   @Before
   public void setup() throws Exception {
     this.objectUnderTest = new FakeGlobalRefDatabase();
diff --git a/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidatorTest.java b/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidatorTest.java
index bb572a8..2c4a1ea 100644
--- a/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidatorTest.java
+++ b/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/BatchRefUpdateValidatorTest.java
@@ -91,7 +91,38 @@
   }
 
   @Test
-  public void immutableChangeShouldNotBeWrittenIntoZk() throws Exception {
+  public void shouldUpdateSharedRefDbForAllRefUpdates() throws IOException {
+    String REF_NAME_A = "refs/changes/01/1/1";
+    String REF_NAME_B = "refs/changes/02/1/1";
+    BatchRefUpdate batchRefUpdate =
+        newBatchUpdate(
+            List.of(
+                new ReceiveCommand(A, B, REF_NAME_A, UPDATE),
+                new ReceiveCommand(A, B, REF_NAME_B, UPDATE)));
+    BatchRefUpdateValidator batchRefUpdateValidator =
+        getRefValidatorForEnforcement(A_TEST_PROJECT_NAME, tmpRefEnforcement);
+
+    doReturn(SharedRefEnforcement.EnforcePolicy.REQUIRED)
+        .when(batchRefUpdateValidator.refEnforcement)
+        .getPolicy(A_TEST_PROJECT_NAME, REF_NAME_A);
+
+    doReturn(true).when(sharedRefDatabase).isUpToDate(any(), any());
+
+    doReturn(true).when(sharedRefDatabase).compareAndPut(any(), any(), any());
+
+    batchRefUpdateValidator.executeBatchUpdateWithValidation(
+        batchRefUpdate, () -> execute(batchRefUpdate), rollbackFunction);
+
+    verify(rollbackFunction, never()).invoke(any());
+
+    List<ReceiveCommand> commands = batchRefUpdate.getCommands();
+    assertThat(commands.size()).isEqualTo(2);
+    commands.forEach(
+        (command) -> assertThat(command.getResult()).isEqualTo(ReceiveCommand.Result.OK));
+  }
+
+  @Test
+  public void immutableChangeShouldNotBeWrittenIntoSharedRefDb() throws Exception {
     String AN_IMMUTABLE_REF = "refs/changes/01/1/1";
 
     List<ReceiveCommand> cmds = Arrays.asList(new ReceiveCommand(A, B, AN_IMMUTABLE_REF, UPDATE));
diff --git a/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/DisabledSharedRefLogger.java b/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/DisabledSharedRefLogger.java
index f9a1e57..d6dd338 100644
--- a/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/DisabledSharedRefLogger.java
+++ b/src/test/java/com/gerritforge/gerrit/globalrefdb/validation/DisabledSharedRefLogger.java
@@ -35,4 +35,7 @@
 
   @Override
   public <T> void logRefUpdate(String project, String refName, T currRef, T newRefValue) {}
+
+  @Override
+  public <T> void logRefUpdate(String project, String refName, T newRefValue) {}
 }