Define ApiModule: expose Forwarder, CommandProcessor and Commands This change exposes DynamicItem<Forwarder> so that other plugins can implement message forwarding using technology of their choice, for example using a GCP pubsub. Also expose DynamicItem<CommandProcessor>. This is not exposed to be overridden but only as a mean for other plugins to inject it and pass received commands back to the high-availability plugin. Injecting the CommandProcessor directly would require exposing also its implementation via the API-Module. This quickly pulls almost complete plugin implementation into the API-Module including the ServerPluginInfoModule which provides plugin specific bindings like "@PluginName String". Since the injector created out of the API module is the parent injector of the injector(s) created in dependent plugins, we would end up with duplicated bindings for the @PluginName and MetricMaker types. Using DynamicItem<CommandProcessor> we only expose the interface via the API module to other plugins. Change-Id: I57c8b27fa4caf6109d797494fac1a91789f056a0
diff --git a/BUILD b/BUILD index da759b9..c4a7d78 100644 --- a/BUILD +++ b/BUILD
@@ -23,6 +23,7 @@ manifest_entries = [ "Gerrit-PluginName: high-availability", "Gerrit-Module: com.ericsson.gerrit.plugins.highavailability.Module", + "Gerrit-ApiModule: com.ericsson.gerrit.plugins.highavailability.ApiModule", "Gerrit-HttpModule: com.ericsson.gerrit.plugins.highavailability.HttpModule", "Gerrit-InitStep: com.ericsson.gerrit.plugins.highavailability.Setup", "Gerrit-ReloadMode: restart",
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/ApiModule.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/ApiModule.java new file mode 100644 index 0000000..fbf5ab5 --- /dev/null +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/ApiModule.java
@@ -0,0 +1,31 @@ +// Copyright (C) 2026 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.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder; +import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.CommandProcessor; +import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.ForwarderCommandsModule; +import com.google.gerrit.extensions.registration.DynamicItem; +import com.google.inject.AbstractModule; + +public class ApiModule extends AbstractModule { + + @Override + protected void configure() { + DynamicItem.itemOf(binder(), Forwarder.class); + DynamicItem.itemOf(binder(), CommandProcessor.class); + install(new ForwarderCommandsModule()); + } +}
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 f75bdaa..4dc9f45 100644 --- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/Configuration.java +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/Configuration.java
@@ -88,7 +88,8 @@ public enum Transport { HTTP, - JGROUPS + JGROUPS, + PROVIDED } @Inject
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 095adee..6227787 100644 --- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/Module.java +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/Module.java
@@ -17,7 +17,10 @@ import com.ericsson.gerrit.plugins.highavailability.autoreindex.AutoReindexModule; import com.ericsson.gerrit.plugins.highavailability.cache.CacheModule; import com.ericsson.gerrit.plugins.highavailability.event.EventModule; +import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder; import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwarderModule; +import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.CommandProcessor; +import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.CommandProcessorImpl; import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.ForwarderCommandsModule; import com.ericsson.gerrit.plugins.highavailability.forwarder.jgroups.JGroupsForwarderModule; import com.ericsson.gerrit.plugins.highavailability.forwarder.rest.RestForwarderModule; @@ -27,6 +30,7 @@ import com.ericsson.gerrit.plugins.highavailability.peers.PeerInfoModule; import com.gerritforge.gerrit.globalrefdb.validation.ProjectDeletedSharedDbCleanup; import com.google.gerrit.extensions.events.ProjectDeletedListener; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.lifecycle.LifecycleModule; import com.google.inject.Inject; @@ -50,17 +54,22 @@ install(new ForwarderModule()); install(new FileBasedLockManager.Module()); + DynamicItem.bind(binder(), CommandProcessor.class).to(CommandProcessorImpl.class); + switch (config.main().transport()) { - case HTTP: + case HTTP -> { install(new RestForwarderModule()); install(new PeerInfoModule(config.peerInfo().strategy())); - break; - case JGROUPS: + } + case JGROUPS -> { install(new ForwarderCommandsModule()); install(new JGroupsForwarderModule()); - break; - default: - throw new IllegalArgumentException("Unsupported transport: " + config.main().transport()); + } + case PROVIDED -> { + // Bind default no-op implementation + // Transport will be provided by another plugin + DynamicItem.bind(binder(), Forwarder.class).to(NoForwarder.class); + } } if (config.cache().synchronize()) {
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/NoForwarder.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/NoForwarder.java new file mode 100644 index 0000000..dc3e8ef --- /dev/null +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/NoForwarder.java
@@ -0,0 +1,95 @@ +// Copyright (C) 2026 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.ericsson.gerrit.plugins.highavailability.forwarder.EventType; +import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder; +import com.ericsson.gerrit.plugins.highavailability.forwarder.IndexEvent; +import com.google.common.flogger.FluentLogger; +import com.google.gerrit.entities.Project.NameKey; +import com.google.gerrit.server.events.Event; +import java.util.concurrent.CompletableFuture; + +/** + * No-Op forwarder implementation + * + * <p>This is used only as a temporary placeholder to avoid null checks until another plugin + * provides a real Forwarder implementation + */ +public class NoForwarder implements Forwarder { + private static final FluentLogger logger = FluentLogger.forEnclosingClass(); + + @Override + public CompletableFuture<Result> indexAccount(int accountId, IndexEvent indexEvent) { + logger.atWarning().log("NoForwarder: indexAccount called with accountId=%d", accountId); + return recoverableFailure(EventType.INDEX_ACCOUNT_UPDATE); + } + + @Override + public CompletableFuture<Result> indexChange( + String projectName, int changeId, IndexEvent indexEvent) { + return recoverableFailure(EventType.INDEX_CHANGE_UPDATE); + } + + @Override + public CompletableFuture<Result> batchIndexChange( + String projectName, int changeId, IndexEvent indexEvent) { + return recoverableFailure(EventType.INDEX_CHANGE_UPDATE_BATCH); + } + + @Override + public CompletableFuture<Result> deleteChangeFromIndex(int changeId, IndexEvent indexEvent) { + return recoverableFailure(EventType.INDEX_CHANGE_DELETION); + } + + @Override + public CompletableFuture<Result> indexGroup(String uuid, IndexEvent indexEvent) { + return recoverableFailure(EventType.INDEX_GROUP_UPDATE); + } + + @Override + public CompletableFuture<Result> indexProject(String projectName, IndexEvent indexEvent) { + return recoverableFailure(EventType.INDEX_PROJECT_UPDATE); + } + + @Override + public CompletableFuture<Result> send(Event event) { + return recoverableFailure(EventType.EVENT_SENT); + } + + @Override + public CompletableFuture<Result> evict(String cacheName, Object key) { + return recoverableFailure(EventType.CACHE_EVICTION); + } + + @Override + public CompletableFuture<Result> addToProjectList(String projectName) { + return recoverableFailure(EventType.PROJECT_LIST_ADDITION); + } + + @Override + public CompletableFuture<Result> removeFromProjectList(String projectName) { + return recoverableFailure(EventType.PROJECT_LIST_DELETION); + } + + @Override + public CompletableFuture<Result> deleteAllChangesForProject(NameKey projectName) { + return recoverableFailure(EventType.INDEX_CHANGE_DELETION_ALL_OF_PROJECT); + } + + private CompletableFuture<Result> recoverableFailure(EventType eventType) { + return CompletableFuture.completedFuture(new Result(eventType, false, true)); + } +}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionHandler.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionHandler.java index 53bc3a1..43b6e4c 100644 --- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionHandler.java +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionHandler.java
@@ -17,15 +17,16 @@ import com.ericsson.gerrit.plugins.highavailability.forwarder.Context; import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder; import com.google.common.cache.RemovalNotification; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.server.cache.CacheRemovalListener; import com.google.inject.Inject; class CacheEvictionHandler<K, V> implements CacheRemovalListener<K, V> { - private final Forwarder forwarder; + private final DynamicItem<Forwarder> forwarder; private final CachePatternMatcher matcher; @Inject - CacheEvictionHandler(Forwarder forwarder, CachePatternMatcher matcher) { + CacheEvictionHandler(DynamicItem<Forwarder> forwarder, CachePatternMatcher matcher) { this.forwarder = forwarder; this.matcher = matcher; } @@ -33,7 +34,7 @@ @Override public void onRemoval(String plugin, String cache, RemovalNotification<K, V> notification) { if (!Context.isForwardedEvent() && !notification.wasEvicted() && matcher.matches(cache)) { - forwarder.evict(cache, notification.getKey()); + forwarder.get().evict(cache, notification.getKey()); } } }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListUpdateHandler.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListUpdateHandler.java index 9ce9536..4281226 100644 --- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListUpdateHandler.java +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListUpdateHandler.java
@@ -19,16 +19,17 @@ import com.google.gerrit.extensions.events.NewProjectCreatedListener; import com.google.gerrit.extensions.events.ProjectDeletedListener; import com.google.gerrit.extensions.events.ProjectEvent; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.inject.Inject; import com.google.inject.Singleton; @Singleton public class ProjectListUpdateHandler implements NewProjectCreatedListener, ProjectDeletedListener { - private final Forwarder forwarder; + private final DynamicItem<Forwarder> forwarder; @Inject - public ProjectListUpdateHandler(Forwarder forwarder) { + public ProjectListUpdateHandler(DynamicItem<Forwarder> forwarder) { this.forwarder = forwarder; } @@ -47,9 +48,9 @@ private void process(ProjectEvent event, boolean delete) { if (!Context.isForwardedEvent()) { if (delete) { - forwarder.removeFromProjectList(event.getProjectName()); + forwarder.get().removeFromProjectList(event.getProjectName()); } else { - forwarder.addToProjectList(event.getProjectName()); + forwarder.get().addToProjectList(event.getProjectName()); } } }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/event/EventHandler.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/event/EventHandler.java index 5ce12df..3060f5f 100644 --- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/event/EventHandler.java +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/event/EventHandler.java
@@ -16,23 +16,24 @@ import com.ericsson.gerrit.plugins.highavailability.forwarder.Context; import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.server.events.Event; import com.google.gerrit.server.events.EventListener; import com.google.gerrit.server.events.ProjectEvent; import com.google.inject.Inject; class EventHandler implements EventListener { - private final Forwarder forwarder; + private final DynamicItem<Forwarder> forwarder; @Inject - EventHandler(Forwarder forwarder) { + EventHandler(DynamicItem<Forwarder> forwarder) { this.forwarder = forwarder; } @Override public void onEvent(Event event) { if (!Context.isForwardedEvent() && event instanceof ProjectEvent) { - forwarder.send(event); + forwarder.get().send(event); } } }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandProcessor.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandProcessor.java index ca30de7..6c40356 100644 --- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandProcessor.java +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandProcessor.java
@@ -1,4 +1,4 @@ -// Copyright (C) 2023 The Android Open Source Project +// Copyright (C) 2026 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. @@ -14,129 +14,14 @@ package com.ericsson.gerrit.plugins.highavailability.forwarder.commands; -import com.ericsson.gerrit.plugins.highavailability.forwarder.CacheEntry; -import com.ericsson.gerrit.plugins.highavailability.forwarder.Context; -import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedCacheEvictionHandler; -import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedEventHandler; -import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexAccountHandler; -import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexBatchChangeHandler; -import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexChangeHandler; -import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexingHandler.Operation; -import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedProjectListUpdateHandler; -import com.ericsson.gerrit.plugins.highavailability.forwarder.ProcessorMetrics; -import com.ericsson.gerrit.plugins.highavailability.forwarder.ProcessorMetricsRegistry; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.flogger.FluentLogger; -import com.google.gerrit.entities.Account; -import com.google.gerrit.server.events.Event; -import com.google.inject.Inject; -import com.google.inject.Singleton; -import java.io.IOException; -import java.time.Instant; -import java.util.Optional; +/** Processes commands received from other nodes */ +public interface CommandProcessor { -@Singleton -public class CommandProcessor { - private static final FluentLogger log = FluentLogger.forEnclosingClass(); - - private final ForwardedIndexChangeHandler indexChangeHandler; - private final ForwardedIndexBatchChangeHandler indexBatchChangeHandler; - private final ForwardedIndexAccountHandler indexAccountHandler; - private final ForwardedCacheEvictionHandler cacheEvictionHandler; - private final ForwardedEventHandler eventHandler; - private final ForwardedProjectListUpdateHandler projectListUpdateHandler; - private final ProcessorMetricsRegistry metricRegistry; - - @Inject - @VisibleForTesting - public CommandProcessor( - ForwardedIndexChangeHandler indexChangeHandler, - ForwardedIndexBatchChangeHandler indexBatchChangeHandler, - ForwardedIndexAccountHandler indexAccountHandler, - ForwardedCacheEvictionHandler cacheEvictionHandler, - ForwardedEventHandler eventHandler, - ForwardedProjectListUpdateHandler projectListUpdateHandler, - ProcessorMetricsRegistry metricRegistry) { - this.indexChangeHandler = indexChangeHandler; - this.indexBatchChangeHandler = indexBatchChangeHandler; - this.indexAccountHandler = indexAccountHandler; - this.cacheEvictionHandler = cacheEvictionHandler; - this.eventHandler = eventHandler; - this.projectListUpdateHandler = projectListUpdateHandler; - this.metricRegistry = metricRegistry; - } - - public boolean handle(Command cmd) { - ProcessorMetrics metrics = metricRegistry.get(cmd.type); - Instant startTime = Instant.now(); - boolean success = false; - - Context.setForwardedEvent(true); - try { - - if (cmd instanceof IndexChange) { - IndexChange indexChange = (IndexChange) cmd; - Operation op = getOperation(indexChange); - try { - ForwardedIndexChangeHandler handler = - indexChange.isBatch() ? indexBatchChangeHandler : indexChangeHandler; - handler.index(indexChange.getId(), op, Optional.empty()); - log.atFine().log( - "Change index %s on change %s done", op.name().toLowerCase(), indexChange.getId()); - } catch (Exception e) { - log.atSevere().withCause(e).log( - "Change index %s on change %s failed", op.name().toLowerCase(), indexChange.getId()); - throw e; - } - - } else if (cmd instanceof IndexAccount) { - IndexAccount indexAccount = (IndexAccount) cmd; - try { - indexAccountHandler.index( - Account.id(indexAccount.getId()), Operation.INDEX, Optional.empty()); - log.atFine().log("Account index update on account %s done", indexAccount.getId()); - } catch (IOException e) { - log.atSevere().withCause(e).log( - "Account index update on account %s failed", indexAccount.getId()); - throw e; - } - - } else if (cmd instanceof EvictCache) { - EvictCache evictCommand = (EvictCache) cmd; - cacheEvictionHandler.evict( - CacheEntry.from(evictCommand.getCacheName(), evictCommand.getKeyJson())); - log.atFine().log( - "Cache eviction %s %s done", evictCommand.getCacheName(), evictCommand.getKeyJson()); - - } else if (cmd instanceof PostEvent) { - Event event = ((PostEvent) cmd).getEvent(); - eventHandler.dispatch(event); - log.atFine().log("Dispatching event %s done", event); - } else if (cmd instanceof AddToProjectList) { - String projectName = ((AddToProjectList) cmd).getProjectName(); - projectListUpdateHandler.update(projectName, false); - - } else if (cmd instanceof RemoveFromProjectList) { - String projectName = ((RemoveFromProjectList) cmd).getProjectName(); - projectListUpdateHandler.update(projectName, true); - } - success = true; - } catch (Exception e) { - success = false; - } finally { - Context.unsetForwardedEvent(); - } - metrics.record(cmd.eventCreatedOn, startTime, success); - return success; - } - - private Operation getOperation(IndexChange cmd) { - if (cmd instanceof IndexChange.Update || cmd instanceof IndexChange.BatchUpdate) { - return Operation.INDEX; - } else if (cmd instanceof IndexChange.Delete) { - return Operation.DELETE; - } else { - throw new IllegalArgumentException("Unknown type of IndexChange command " + cmd.getClass()); - } - } + /** + * Processes the given command. + * + * @param cmd the command to process + * @return true if the command was successfully processed, false otherwise + */ + boolean handle(Command cmd); }
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandProcessorImpl.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandProcessorImpl.java new file mode 100644 index 0000000..cadfaea --- /dev/null +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/commands/CommandProcessorImpl.java
@@ -0,0 +1,143 @@ +// Copyright (C) 2023 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.forwarder.commands; + +import com.ericsson.gerrit.plugins.highavailability.forwarder.CacheEntry; +import com.ericsson.gerrit.plugins.highavailability.forwarder.Context; +import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedCacheEvictionHandler; +import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedEventHandler; +import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexAccountHandler; +import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexBatchChangeHandler; +import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexChangeHandler; +import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedIndexingHandler.Operation; +import com.ericsson.gerrit.plugins.highavailability.forwarder.ForwardedProjectListUpdateHandler; +import com.ericsson.gerrit.plugins.highavailability.forwarder.ProcessorMetrics; +import com.ericsson.gerrit.plugins.highavailability.forwarder.ProcessorMetricsRegistry; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.flogger.FluentLogger; +import com.google.gerrit.entities.Account; +import com.google.gerrit.server.events.Event; +import com.google.inject.Inject; +import com.google.inject.Singleton; +import java.io.IOException; +import java.time.Instant; +import java.util.Optional; + +@Singleton +public class CommandProcessorImpl implements CommandProcessor { + private static final FluentLogger log = FluentLogger.forEnclosingClass(); + + private final ForwardedIndexChangeHandler indexChangeHandler; + private final ForwardedIndexBatchChangeHandler indexBatchChangeHandler; + private final ForwardedIndexAccountHandler indexAccountHandler; + private final ForwardedCacheEvictionHandler cacheEvictionHandler; + private final ForwardedEventHandler eventHandler; + private final ForwardedProjectListUpdateHandler projectListUpdateHandler; + private final ProcessorMetricsRegistry metricRegistry; + + @Inject + @VisibleForTesting + public CommandProcessorImpl( + ForwardedIndexChangeHandler indexChangeHandler, + ForwardedIndexBatchChangeHandler indexBatchChangeHandler, + ForwardedIndexAccountHandler indexAccountHandler, + ForwardedCacheEvictionHandler cacheEvictionHandler, + ForwardedEventHandler eventHandler, + ForwardedProjectListUpdateHandler projectListUpdateHandler, + ProcessorMetricsRegistry metricRegistry) { + this.indexChangeHandler = indexChangeHandler; + this.indexBatchChangeHandler = indexBatchChangeHandler; + this.indexAccountHandler = indexAccountHandler; + this.cacheEvictionHandler = cacheEvictionHandler; + this.eventHandler = eventHandler; + this.projectListUpdateHandler = projectListUpdateHandler; + this.metricRegistry = metricRegistry; + } + + @Override + public boolean handle(Command cmd) { + ProcessorMetrics metrics = metricRegistry.get(cmd.type); + Instant startTime = Instant.now(); + boolean success = false; + + Context.setForwardedEvent(true); + try { + + if (cmd instanceof IndexChange) { + IndexChange indexChange = (IndexChange) cmd; + Operation op = getOperation(indexChange); + try { + ForwardedIndexChangeHandler handler = + indexChange.isBatch() ? indexBatchChangeHandler : indexChangeHandler; + handler.index(indexChange.getId(), op, Optional.empty()); + log.atFine().log( + "Change index %s on change %s done", op.name().toLowerCase(), indexChange.getId()); + } catch (Exception e) { + log.atSevere().withCause(e).log( + "Change index %s on change %s failed", op.name().toLowerCase(), indexChange.getId()); + throw e; + } + + } else if (cmd instanceof IndexAccount) { + IndexAccount indexAccount = (IndexAccount) cmd; + try { + indexAccountHandler.index( + Account.id(indexAccount.getId()), Operation.INDEX, Optional.empty()); + log.atFine().log("Account index update on account %s done", indexAccount.getId()); + } catch (IOException e) { + log.atSevere().withCause(e).log( + "Account index update on account %s failed", indexAccount.getId()); + throw e; + } + + } else if (cmd instanceof EvictCache) { + EvictCache evictCommand = (EvictCache) cmd; + cacheEvictionHandler.evict( + CacheEntry.from(evictCommand.getCacheName(), evictCommand.getKeyJson())); + log.atFine().log( + "Cache eviction %s %s done", evictCommand.getCacheName(), evictCommand.getKeyJson()); + + } else if (cmd instanceof PostEvent) { + Event event = ((PostEvent) cmd).getEvent(); + eventHandler.dispatch(event); + log.atFine().log("Dispatching event %s done", event); + } else if (cmd instanceof AddToProjectList) { + String projectName = ((AddToProjectList) cmd).getProjectName(); + projectListUpdateHandler.update(projectName, false); + + } else if (cmd instanceof RemoveFromProjectList) { + String projectName = ((RemoveFromProjectList) cmd).getProjectName(); + projectListUpdateHandler.update(projectName, true); + } + success = true; + } catch (Exception e) { + success = false; + } finally { + Context.unsetForwardedEvent(); + } + metrics.record(cmd.eventCreatedOn, startTime, success); + return success; + } + + private Operation getOperation(IndexChange cmd) { + if (cmd instanceof IndexChange.Update || cmd instanceof IndexChange.BatchUpdate) { + return Operation.INDEX; + } else if (cmd instanceof IndexChange.Delete) { + return Operation.DELETE; + } else { + throw new IllegalArgumentException("Unknown type of IndexChange command " + cmd.getClass()); + } + } +}
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderModule.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderModule.java index 98600f1..3d3a5b7 100644 --- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderModule.java +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/JGroupsForwarderModule.java
@@ -17,6 +17,7 @@ import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder; import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder.Result; import com.ericsson.gerrit.plugins.highavailability.peers.jgroups.JChannelProviderModule; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.lifecycle.LifecycleModule; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; @@ -28,7 +29,7 @@ @Override protected void configure() { - bind(Forwarder.class).to(JGroupsForwarder.class); + DynamicItem.bind(binder(), Forwarder.class).to(JGroupsForwarder.class); bind(MessageDispatcher.class).toProvider(MessageDispatcherProvider.class).in(Scopes.SINGLETON); bind(RequestHandler.class).to(JGroupsMessageProcessor.class); install(new JChannelProviderModule());
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderModule.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderModule.java index 712e7f4..f1c58e6 100644 --- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderModule.java +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderModule.java
@@ -17,6 +17,7 @@ import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder; import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder.Result; import com.ericsson.gerrit.plugins.highavailability.forwarder.InstantTypeAdapter; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.server.events.EventGson; import com.google.gson.Gson; import com.google.inject.AbstractModule; @@ -34,7 +35,7 @@ protected void configure() { bind(CloseableHttpClient.class).toProvider(HttpClientProvider.class).in(Scopes.SINGLETON); bind(HttpSession.class); - bind(Forwarder.class).to(RestForwarder.class); + DynamicItem.bind(binder(), Forwarder.class).to(RestForwarder.class); bind(new TypeLiteral<FailsafeExecutor<Result>>() {}) .annotatedWith(RestForwarderExecutor.class)
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandler.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandler.java index 6475d99..0b1ff7f 100644 --- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandler.java +++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandler.java
@@ -23,6 +23,7 @@ import com.google.gerrit.extensions.events.ChangeIndexedListener; import com.google.gerrit.extensions.events.GroupIndexedListener; import com.google.gerrit.extensions.events.ProjectIndexedListener; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.inject.Inject; import java.util.Optional; @@ -32,13 +33,15 @@ GroupIndexedListener, ProjectIndexedListener { private static final FluentLogger log = FluentLogger.forEnclosingClass(); - private final Forwarder forwarder; + private final DynamicItem<Forwarder> forwarder; private final ChangeCheckerImpl.Factory changeChecker; private final CurrentRequestContext currCtx; @Inject IndexEventHandler( - Forwarder forwarder, ChangeCheckerImpl.Factory changeChecker, CurrentRequestContext currCtx) { + DynamicItem<Forwarder> forwarder, + ChangeCheckerImpl.Factory changeChecker, + CurrentRequestContext currCtx) { this.forwarder = forwarder; this.changeChecker = changeChecker; this.currCtx = currCtx; @@ -49,7 +52,7 @@ currCtx.onlyWithContext( (ctx) -> { if (!Context.isForwardedEvent()) { - forwarder.indexAccount(id, new IndexEvent()); + forwarder.get().indexAccount(id, new IndexEvent()); } }); } @@ -66,7 +69,7 @@ private void executeAllChangesDeletedForProject(String projectName) { if (!Context.isForwardedEvent()) { - forwarder.deleteAllChangesForProject(Project.nameKey(projectName)); + forwarder.get().deleteAllChangesForProject(Project.nameKey(projectName)); } } @@ -80,9 +83,9 @@ } if (Thread.currentThread().getName().contains("Batch")) { - forwarder.batchIndexChange(projectName, id, indexEvent.get()); + forwarder.get().batchIndexChange(projectName, id, indexEvent.get()); } else { - forwarder.indexChange(projectName, id, indexEvent.get()); + forwarder.get().indexChange(projectName, id, indexEvent.get()); } } catch (Exception e) { log.atWarning().withCause(e).log("Unable to create task to reindex change %s", changeId); @@ -93,21 +96,21 @@ @Override public void onChangeDeleted(int id) { if (!Context.isForwardedEvent()) { - forwarder.deleteChangeFromIndex(id, new IndexEvent()); + forwarder.get().deleteChangeFromIndex(id, new IndexEvent()); } } @Override public void onProjectIndexed(String projectName) { if (!Context.isForwardedEvent()) { - forwarder.indexProject(projectName, new IndexEvent()); + forwarder.get().indexProject(projectName, new IndexEvent()); } } @Override public void onGroupIndexed(String groupUUID) { if (!Context.isForwardedEvent()) { - forwarder.indexGroup(groupUUID, new IndexEvent()); + forwarder.get().indexGroup(groupUUID, new IndexEvent()); } } }
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md index b089091..737b354 100644 --- a/src/main/resources/Documentation/config.md +++ b/src/main/resources/Documentation/config.md
@@ -73,6 +73,18 @@ maxTries = 100 ``` +### Transport implementation provided by another plugin + +In this case another plugin extends the @PLUGIN@ plugin and provides messaging +implementation. +``` +[main] + transport = provided + sharedDirectory = /directory/accessible/from/both/instances +[autoReindex] + enabled = false +``` + ```main.sharedDirectory``` : Path to a directory accessible from both instances. When given as a relative path, then it is resolved against the $SITE_PATH @@ -82,9 +94,10 @@ is "shared". ```main.transport``` -: Message transport layer. Could be: `http` or `jgroups`. +: Message transport layer. Could be: `http`, `jgroups` or `provided`. When not specificed the default is `http`. - When set to `jgroups` then all `peerInfo.*` sections are unnecessary and ignored. + When set to `jgroups` or `provided` then all `peerInfo.*` sections are + unnecessary and ignored. ```autoReindex.enabled``` : Enable the tracking of the latest change indexed under data/high-availability
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionHandlerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionHandlerTest.java index 3d091a0..cd5a477 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionHandlerTest.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionHandlerTest.java
@@ -20,6 +20,7 @@ import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder; import com.google.common.cache.RemovalCause; import com.google.common.cache.RemovalNotification; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.server.config.PluginConfigFactory; import com.google.gerrit.server.config.SitePaths; import java.io.IOException; @@ -34,7 +35,7 @@ @RunWith(MockitoJUnitRunner.class) public class CacheEvictionHandlerTest { - @Mock private Forwarder forwarder; + @Mock private DynamicItem<Forwarder> forwarder; @Mock private PluginConfigFactory pluginConfigFactoryMock; private static final Path SITE_PATH = Paths.get("/site_path");
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionIT.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionIT.java index 180c68f..f44be49 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionIT.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/CacheEvictionIT.java
@@ -48,6 +48,7 @@ @UseSsh @TestPlugin( name = "high-availability", + apiModule = "com.ericsson.gerrit.plugins.highavailability.ApiModule", sysModule = "com.ericsson.gerrit.plugins.highavailability.Module", httpModule = "com.ericsson.gerrit.plugins.highavailability.HttpModule") public class CacheEvictionIT extends LightweightPluginDaemonTest {
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListIT.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListIT.java index 36c775c..6fa508e 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListIT.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListIT.java
@@ -38,6 +38,7 @@ @TestPlugin( name = "high-availability", + apiModule = "com.ericsson.gerrit.plugins.highavailability.ApiModule", sysModule = "com.ericsson.gerrit.plugins.highavailability.Module", httpModule = "com.ericsson.gerrit.plugins.highavailability.HttpModule") public class ProjectListIT extends LightweightPluginDaemonTest {
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListUpdateHandlerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListUpdateHandlerTest.java index 1bd2aed..e4fea74 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListUpdateHandlerTest.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/cache/ProjectListUpdateHandlerTest.java
@@ -23,6 +23,8 @@ import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder; import com.google.gerrit.extensions.events.NewProjectCreatedListener; import com.google.gerrit.extensions.events.ProjectDeletedListener; +import com.google.gerrit.extensions.registration.DynamicItem; +import com.google.inject.Inject; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,10 +36,12 @@ private ProjectListUpdateHandler handler; @Mock private Forwarder forwarder; + @Inject DynamicItem<Forwarder> forwarderItem; @Before public void setUp() { - handler = new ProjectListUpdateHandler(forwarder); + forwarderItem = DynamicItem.itemOf(Forwarder.class, forwarder); + handler = new ProjectListUpdateHandler(forwarderItem); } @Test
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/event/EventHandlerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/event/EventHandlerTest.java index 988064e..6c12b1d 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/event/EventHandlerTest.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/event/EventHandlerTest.java
@@ -20,8 +20,10 @@ import com.ericsson.gerrit.plugins.highavailability.forwarder.Context; import com.ericsson.gerrit.plugins.highavailability.forwarder.Forwarder; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.server.events.Event; import com.google.gerrit.server.events.ProjectEvent; +import com.google.inject.Inject; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @@ -33,10 +35,12 @@ private EventHandler eventHandler; @Mock private Forwarder forwarder; + @Inject DynamicItem<Forwarder> forwarderItem; @Before public void setUp() { - eventHandler = new EventHandler(forwarder); + forwarderItem = DynamicItem.itemOf(Forwarder.class, forwarder); + eventHandler = new EventHandler(forwarderItem); } @Test
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessorTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessorTest.java index d17b3f1..bca7801 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessorTest.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/jgroups/MessageProcessorTest.java
@@ -34,7 +34,7 @@ import com.ericsson.gerrit.plugins.highavailability.forwarder.ProcessorMetrics; import com.ericsson.gerrit.plugins.highavailability.forwarder.ProcessorMetricsRegistry; import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.AddToProjectList; -import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.CommandProcessor; +import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.CommandProcessorImpl; import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.EvictCache; import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.ForwarderCommandsModule; import com.ericsson.gerrit.plugins.highavailability.forwarder.commands.IndexAccount; @@ -94,7 +94,7 @@ processor = new JGroupsMessageProcessor( gson, - new CommandProcessor( + new CommandProcessorImpl( indexChangeHandler, indexBatchChangeHandler, indexAccountHandler,
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/ForwardedCacheEvictionHandlerIT.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/ForwardedCacheEvictionHandlerIT.java index 1e5cc3d..4488cc4 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/ForwardedCacheEvictionHandlerIT.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/ForwardedCacheEvictionHandlerIT.java
@@ -40,6 +40,7 @@ @TestPlugin( name = "high-availability", + apiModule = "com.ericsson.gerrit.plugins.highavailability.ApiModule", sysModule = "com.ericsson.gerrit.plugins.highavailability.Module", httpModule = "com.ericsson.gerrit.plugins.highavailability.HttpModule") public class ForwardedCacheEvictionHandlerIT extends LightweightPluginDaemonTest {
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/ProjectListRestApiServletIT.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/ProjectListRestApiServletIT.java index e838cb3..caea2aa 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/ProjectListRestApiServletIT.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/ProjectListRestApiServletIT.java
@@ -25,6 +25,7 @@ @TestPlugin( name = "high-availability", + apiModule = "com.ericsson.gerrit.plugins.highavailability.ApiModule", sysModule = "com.ericsson.gerrit.plugins.highavailability.Module", httpModule = "com.ericsson.gerrit.plugins.highavailability.HttpModule") public class ProjectListRestApiServletIT extends LightweightPluginDaemonTest {
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderServletModuleIT.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderServletModuleIT.java index 2406443..880ec04 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderServletModuleIT.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/rest/RestForwarderServletModuleIT.java
@@ -25,6 +25,7 @@ @TestPlugin( name = "high-availability", + apiModule = "com.ericsson.gerrit.plugins.highavailability.ApiModule", sysModule = "com.ericsson.gerrit.plugins.highavailability.Module", httpModule = "com.ericsson.gerrit.plugins.highavailability.HttpModule") public class RestForwarderServletModuleIT extends LightweightPluginDaemonTest {
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 fe6cfce..3010d9c 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
@@ -46,6 +46,7 @@ @NoHttpd @TestPlugin( name = "high-availability", + apiModule = "com.ericsson.gerrit.plugins.highavailability.ApiModule", sysModule = "com.ericsson.gerrit.plugins.highavailability.Module", httpModule = "com.ericsson.gerrit.plugins.highavailability.HttpModule") public abstract class AbstractIndexForwardingIT extends LightweightPluginDaemonTest {
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/ChangeCheckerIT.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/ChangeCheckerIT.java index febf8f0..ebf966f 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/ChangeCheckerIT.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/ChangeCheckerIT.java
@@ -20,6 +20,7 @@ import com.google.gerrit.acceptance.LightweightPluginDaemonTest; import com.google.gerrit.acceptance.PushOneCommit.Result; import com.google.gerrit.acceptance.TestPlugin; +import com.google.gerrit.acceptance.UseLocalDisk; import com.google.gerrit.entities.RefNames; import java.io.IOException; import java.util.Optional; @@ -29,6 +30,7 @@ @TestPlugin( name = "high-availability", + apiModule = "com.ericsson.gerrit.plugins.highavailability.ApiModule", sysModule = "com.ericsson.gerrit.plugins.highavailability.Module", httpModule = "com.ericsson.gerrit.plugins.highavailability.HttpModule") public class ChangeCheckerIT extends LightweightPluginDaemonTest { @@ -42,6 +44,7 @@ } @Test + @UseLocalDisk public void shouldPopulateMetaSha() throws Exception { Result change = createChange(); ChangeChecker changeChecker = changeCheckerFactory.create(change.getChangeId()); @@ -54,6 +57,7 @@ } @Test + @UseLocalDisk public void shouldReturnIsUpToDateTrueWhenEventContainsCorrectMetaAndTargetSha() throws Exception { Result change = createChange(); @@ -64,6 +68,7 @@ } @Test + @UseLocalDisk public void shouldReturnIsUpToDateTrueWhenTargetShaIsNull() throws Exception { Result change = createChange(); ChangeChecker changeChecker = changeCheckerFactory.create(change.getChangeId()); @@ -80,6 +85,7 @@ } @Test + @UseLocalDisk public void shouldReturnFalseWhenMetaShaIsNotUpToDate() throws Exception { String testMetaRefSha = "6212efebe6e8b9f439a8ad013243e602afab7441"; Result change = createChange(); @@ -97,6 +103,7 @@ } @Test + @UseLocalDisk public void shouldReturnFalseWhenTargetShaIsNotUpToDate() throws Exception { String testTargetRefSha = "abed47baf2818a86b68cf712073a748a6b5b293e"; Result change = createChange();
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandlerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandlerTest.java index a986b90..22c2eb0 100644 --- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandlerTest.java +++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/index/IndexEventHandlerTest.java
@@ -31,9 +31,11 @@ import com.google.gerrit.entities.Account; import com.google.gerrit.entities.AccountGroup; import com.google.gerrit.entities.Change; +import com.google.gerrit.extensions.registration.DynamicItem; import com.google.gerrit.server.util.OneOffRequestContext; import com.google.gerrit.server.util.RequestContext; import com.google.gerrit.server.util.ThreadLocalRequestContext; +import com.google.inject.Inject; import java.util.Optional; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; @@ -52,6 +54,7 @@ private IndexEventHandler indexEventHandler; @Mock private Forwarder forwarder; + @Inject private DynamicItem<Forwarder> forwarderItem; @Mock private ChangeCheckerImpl.Factory changeCheckerFactoryMock; @Mock private ChangeChecker changeCheckerMock; private Change.Id changeId; @@ -89,11 +92,12 @@ .thenReturn( CompletableFuture.completedFuture(new Result(EventType.INDEX_CHANGE_UPDATE, true))); + forwarderItem = DynamicItem.itemOf(Forwarder.class, forwarder); setUpIndexEventHandler(currCtx); } public void setUpIndexEventHandler(CurrentRequestContext currCtx) throws Exception { - indexEventHandler = new IndexEventHandler(forwarder, changeCheckerFactoryMock, currCtx); + indexEventHandler = new IndexEventHandler(forwarderItem, changeCheckerFactoryMock, currCtx); } @Test