Merge branch 'stable-3.10' into stable-3.11

* stable-3.10:
  Reintroduce Forwarded(Batch)IndexExecutor for indexing threads
  Add Failsafe in the ForwardedIndexExecutorProvider name

Change-Id: I45c48cf3dae0d0a8f4917929827d28069778cebd
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedBatchIndexExecutorProvider.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedBatchIndexExecutorProvider.java
index 64fe3b1..a3a7e64 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedBatchIndexExecutorProvider.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedBatchIndexExecutorProvider.java
@@ -1,4 +1,4 @@
-// Copyright (C) 2021 The Android Open Source Project
+// Copyright (C) 2024 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.
@@ -15,19 +15,22 @@
 package com.ericsson.gerrit.plugins.highavailability.index;
 
 import com.ericsson.gerrit.plugins.highavailability.Configuration;
+import com.ericsson.gerrit.plugins.highavailability.ExecutorProvider;
+import com.google.gerrit.common.UsedAt;
+import com.google.gerrit.server.git.WorkQueue;
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
 @Singleton
-class ForwardedBatchIndexExecutorProvider extends ForwardedIndexExecutorProvider {
+class ForwardedBatchIndexExecutorProvider extends ExecutorProvider {
+
+  @UsedAt(UsedAt.Project.PLUGIN_MULTI_SITE)
+  public static final String FORWARDED_BATCH_INDEX_EVENT_THREAD_PREFIX =
+      "Forwarded-BatchIndex-Event";
 
   @Inject
-  ForwardedBatchIndexExecutorProvider(Configuration cfg) {
-    super(cfg);
-  }
-
-  @Override
-  protected int threadPoolSize(Configuration cfg) {
-    return cfg.index().batchThreadPoolSize();
+  ForwardedBatchIndexExecutorProvider(WorkQueue workQueue, Configuration config) {
+    super(
+        workQueue, config.index().batchThreadPoolSize(), FORWARDED_BATCH_INDEX_EVENT_THREAD_PREFIX);
   }
 }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedBatchIndexFailsafeExecutorProvider.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedBatchIndexFailsafeExecutorProvider.java
new file mode 100644
index 0000000..f52b3fe
--- /dev/null
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedBatchIndexFailsafeExecutorProvider.java
@@ -0,0 +1,30 @@
+// Copyright (C) 2021 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.index;
+
+import com.ericsson.gerrit.plugins.highavailability.Configuration;
+import com.ericsson.gerrit.plugins.highavailability.ExecutorProvider;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+@Singleton
+class ForwardedBatchIndexFailsafeExecutorProvider extends ForwardedIndexFailsafeExecutorProvider {
+
+  @Inject
+  ForwardedBatchIndexFailsafeExecutorProvider(
+      Configuration cfg, @ForwardedBatchIndexExecutor ExecutorProvider indexExecutorProvider) {
+    super(cfg, indexExecutorProvider);
+  }
+}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedIndexExecutorProvider.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedIndexExecutorProvider.java
index e4bf7f3..da623df 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedIndexExecutorProvider.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedIndexExecutorProvider.java
@@ -15,45 +15,20 @@
 package com.ericsson.gerrit.plugins.highavailability.index;
 
 import com.ericsson.gerrit.plugins.highavailability.Configuration;
-import com.google.common.flogger.FluentLogger;
+import com.ericsson.gerrit.plugins.highavailability.ExecutorProvider;
+import com.google.gerrit.common.UsedAt;
+import com.google.gerrit.server.git.WorkQueue;
 import com.google.inject.Inject;
-import com.google.inject.Provider;
 import com.google.inject.Singleton;
-import dev.failsafe.Failsafe;
-import dev.failsafe.FailsafeExecutor;
-import dev.failsafe.RetryPolicy;
-import java.io.IOException;
-import java.util.concurrent.Executors;
 
 @Singleton
-public class ForwardedIndexExecutorProvider implements Provider<FailsafeExecutor<Boolean>> {
-  protected static final FluentLogger log = FluentLogger.forEnclosingClass();
-  private final Configuration cfg;
+public class ForwardedIndexExecutorProvider extends ExecutorProvider {
+
+  @UsedAt(UsedAt.Project.PLUGIN_MULTI_SITE)
+  public static final String FORWARDED_INDEX_EVENT_THREAD_PREFIX = "Forwarded-Index-Event";
 
   @Inject
-  public ForwardedIndexExecutorProvider(Configuration cfg) {
-    this.cfg = cfg;
-  }
-
-  @Override
-  public FailsafeExecutor<Boolean> get() {
-    RetryPolicy<Boolean> retryPolicy =
-        RetryPolicy.<Boolean>builder()
-            .withMaxAttempts(cfg.index().maxTries())
-            .withDelay(cfg.index().retryInterval())
-            .onRetry(e -> log.atFine().log("Retrying event %s", e))
-            .onRetriesExceeded(
-                e ->
-                    log.atWarning().log(
-                        "%d index retries exceeded for event %s", cfg.index().maxTries(), e))
-            .handleResult(false)
-            .abortOn(IOException.class)
-            .build();
-    // TODO: the executor shall be created by workQueue.createQueue(...)
-    return Failsafe.with(retryPolicy).with(Executors.newScheduledThreadPool(threadPoolSize(cfg)));
-  }
-
-  protected int threadPoolSize(Configuration cfg) {
-    return cfg.index().threadPoolSize();
+  ForwardedIndexExecutorProvider(WorkQueue workQueue, Configuration config) {
+    super(workQueue, config.index().threadPoolSize(), FORWARDED_INDEX_EVENT_THREAD_PREFIX);
   }
 }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedIndexFailsafeExecutorProvider.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedIndexFailsafeExecutorProvider.java
new file mode 100644
index 0000000..7bae94a
--- /dev/null
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/ForwardedIndexFailsafeExecutorProvider.java
@@ -0,0 +1,57 @@
+// Copyright (C) 2018 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.index;
+
+import com.ericsson.gerrit.plugins.highavailability.Configuration;
+import com.ericsson.gerrit.plugins.highavailability.ExecutorProvider;
+import com.google.common.flogger.FluentLogger;
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+import com.google.inject.Singleton;
+import dev.failsafe.Failsafe;
+import dev.failsafe.FailsafeExecutor;
+import dev.failsafe.RetryPolicy;
+import java.io.IOException;
+
+@Singleton
+public class ForwardedIndexFailsafeExecutorProvider implements Provider<FailsafeExecutor<Boolean>> {
+  protected static final FluentLogger log = FluentLogger.forEnclosingClass();
+  private final Configuration cfg;
+  private final ExecutorProvider indexExecutorProvider;
+
+  @Inject
+  public ForwardedIndexFailsafeExecutorProvider(
+      Configuration cfg, @ForwardedIndexExecutor ExecutorProvider indexExecutorProvider) {
+    this.cfg = cfg;
+    this.indexExecutorProvider = indexExecutorProvider;
+  }
+
+  @Override
+  public FailsafeExecutor<Boolean> get() {
+    RetryPolicy<Boolean> retryPolicy =
+        RetryPolicy.<Boolean>builder()
+            .withMaxAttempts(cfg.index().maxTries())
+            .withDelay(cfg.index().retryInterval())
+            .onRetry(e -> log.atFine().log("Retrying event %s", e))
+            .onRetriesExceeded(
+                e ->
+                    log.atWarning().log(
+                        "%d index retries exceeded for event %s", cfg.index().maxTries(), e))
+            .handleResult(false)
+            .abortOn(IOException.class)
+            .build();
+    return Failsafe.with(retryPolicy).with(indexExecutorProvider.get());
+  }
+}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexModule.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexModule.java
index 208bc86..1db3721 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexModule.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexModule.java
@@ -14,6 +14,7 @@
 
 package com.ericsson.gerrit.plugins.highavailability.index;
 
+import com.ericsson.gerrit.plugins.highavailability.ExecutorProvider;
 import com.google.gerrit.extensions.events.AccountIndexedListener;
 import com.google.gerrit.extensions.events.ChangeIndexedListener;
 import com.google.gerrit.extensions.events.GroupIndexedListener;
@@ -31,12 +32,20 @@
   protected void configure() {
     bind(new TypeLiteral<FailsafeExecutor<Boolean>>() {})
         .annotatedWith(ForwardedIndexExecutor.class)
-        .toProvider(ForwardedIndexExecutorProvider.class)
+        .toProvider(ForwardedIndexFailsafeExecutorProvider.class)
+        .in(Scopes.SINGLETON);
+    bind(ExecutorProvider.class)
+        .annotatedWith(ForwardedIndexExecutor.class)
+        .to(ForwardedIndexExecutorProvider.class)
         .in(Scopes.SINGLETON);
 
     bind(new TypeLiteral<FailsafeExecutor<Boolean>>() {})
         .annotatedWith(ForwardedBatchIndexExecutor.class)
-        .toProvider(ForwardedBatchIndexExecutorProvider.class)
+        .toProvider(ForwardedBatchIndexFailsafeExecutorProvider.class)
+        .in(Scopes.SINGLETON);
+    bind(ExecutorProvider.class)
+        .annotatedWith(ForwardedBatchIndexExecutor.class)
+        .to(ForwardedBatchIndexExecutorProvider.class)
         .in(Scopes.SINGLETON);
 
     DynamicSet.bind(binder(), ChangeIndexedListener.class)
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandlerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandlerTest.java
index 27d5b2d..cc6939c 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandlerTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedIndexChangeHandlerTest.java
@@ -30,6 +30,7 @@
 import com.ericsson.gerrit.plugins.highavailability.index.ChangeChecker;
 import com.ericsson.gerrit.plugins.highavailability.index.ChangeCheckerImpl;
 import com.ericsson.gerrit.plugins.highavailability.index.ForwardedIndexExecutorProvider;
+import com.ericsson.gerrit.plugins.highavailability.index.ForwardedIndexFailsafeExecutorProvider;
 import com.google.gerrit.entities.Change;
 import com.google.gerrit.entities.Project;
 import com.google.gerrit.server.index.change.ChangeIndexer;
@@ -40,6 +41,7 @@
 import java.time.Duration;
 import java.util.Optional;
 import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executors;
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -69,6 +71,7 @@
   @Mock private ChangeCheckerImpl.Factory changeCheckerFactoryMock;
   @Mock private ChangeChecker changeCheckerAbsentMock;
   @Mock private ChangeChecker changeCheckerPresentMock;
+  @Mock private ForwardedIndexExecutorProvider indexExecutorProviderMock;
   private ForwardedIndexChangeHandler handler;
   private Change.Id id;
 
@@ -79,7 +82,9 @@
     when(configMock.index().maxTries()).thenReturn(3);
     when(configMock.index().retryInterval()).thenReturn(Duration.ofMillis(10));
     when(changeCheckerFactoryMock.create(any())).thenReturn(changeCheckerAbsentMock);
-    FailsafeExecutor<Boolean> indexExecutor = new ForwardedIndexExecutorProvider(configMock).get();
+    when(indexExecutorProviderMock.get()).thenReturn(Executors.newScheduledThreadPool(2));
+    FailsafeExecutor<Boolean> indexExecutor =
+        new ForwardedIndexFailsafeExecutorProvider(configMock, indexExecutorProviderMock).get();
     handler =
         new ForwardedIndexChangeHandler(
             indexerMock, indexExecutor, ctxMock, changeCheckerFactoryMock);