Retry review on lock failures

The review api is prone to lock failures as there will be a contention
to lock the notedb ref. Retrying on lock failures will help mitigate
this. Retries have already been implemented in REST API code path at
a high enough layer (RestApiServlet) so that it applies for all REST
APIs. But when invoking review api internally from a plugin won't
enable the retires defined in RestApiServlet.

Change-Id: Ifa9d9a80b1be56c755b7d248941a9404f84dc1a5
diff --git a/src/main/java/com/googlesource/gerrit/plugins/depends/on/ChangeMessageStore.java b/src/main/java/com/googlesource/gerrit/plugins/depends/on/ChangeMessageStore.java
index 9840df1..a125a88 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/depends/on/ChangeMessageStore.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/depends/on/ChangeMessageStore.java
@@ -28,23 +28,20 @@
 import com.google.gerrit.server.change.ChangeResource;
 import com.google.gerrit.server.change.RevisionResource;
 import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import com.google.gerrit.server.permissions.PermissionBackendException;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
 import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.restapi.change.PostReview;
+import com.google.gerrit.server.update.RetryHelper;
 import com.google.gerrit.server.update.UpdateException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.googlesource.gerrit.plugins.depends.on.extensions.DependencyResolver;
 import com.googlesource.gerrit.plugins.depends.on.formats.Comment;
-import java.io.IOException;
 import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
 import java.util.stream.Collectors;
-import org.eclipse.jgit.errors.ConfigInvalidException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -61,6 +58,7 @@
   protected final Resolver resolver;
   protected final ChangeNotes.Factory changeNotesFactory;
   protected final ChangeMessagesUtil cmUtil;
+  protected final RetryHelper retryHelper;
 
   @Inject
   public ChangeMessageStore(
@@ -69,13 +67,15 @@
       CurrentUser currentUser,
       Resolver resolver,
       ChangeNotes.Factory changeNotesFactory,
-      ChangeMessagesUtil cmUtil) {
+      ChangeMessagesUtil cmUtil,
+      RetryHelper retryHelper) {
     this.reviewProvider = reviewProvider;
     this.changeResourceFactory = changeResourceFactory;
     this.currentUser = currentUser;
     this.resolver = resolver;
     this.changeNotesFactory = changeNotesFactory;
     this.cmUtil = cmUtil;
+    this.retryHelper = retryHelper;
   }
 
   /**
@@ -143,13 +143,15 @@
     ChangeResource changeResource = changeResourceFactory.create(changeNotes, currentUser);
     PatchSet patchSet = changeNotes.load().getPatchSets().get(patchSetId);
     try {
-      reviewProvider.get().apply(new RevisionResource(changeResource, patchSet), review);
-    } catch (RestApiException
-        | UpdateException
-        | IOException
-        | PermissionBackendException
-        | ConfigInvalidException
-        | PatchListNotAvailableException e) {
+      retryHelper
+          .changeUpdate(
+              "changeUpdate",
+              updateFactory ->
+                  reviewProvider
+                      .get()
+                      .apply(new RevisionResource(changeResource, patchSet), review))
+          .call();
+    } catch (RestApiException | UpdateException e) {
       log.error("Unable to post auto-copied review comment", e);
     }
   }