Merge branch 'stable-3.2'
* stable-3.2:
Set forward context for events having a different instanceId
Change-Id: I23e02d50add39f48e99b2c944452e5d3694e3778
diff --git a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedAwareEventBroker.java b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedAwareEventBroker.java
index 700d5e1..fb651b7 100644
--- a/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedAwareEventBroker.java
+++ b/src/main/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedAwareEventBroker.java
@@ -24,6 +24,7 @@
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.project.ProjectCache;
import com.google.inject.Inject;
+import java.util.Objects;
import javax.annotation.Nullable;
class ForwardedAwareEventBroker extends EventBroker {
@@ -45,8 +46,19 @@
gerritInstanceId);
}
+ private boolean isProducedByLocalInstance(Event event) {
+ return Objects.equals(event.instanceId, gerritInstanceId);
+ }
+
@Override
protected void fireEventForUnrestrictedListeners(Event event) {
+ // An event should not be dispatched when it is "forwarded".
+ // Meaning, it was either produced somewhere else
+ if (!isProducedByLocalInstance(event)) {
+ Context.setForwardedEvent(true);
+ }
+ // or it was consumed by the high-availability rest endpoint and
+ // thus the context of its consumption has already been set to "forwarded".
if (!Context.isForwardedEvent()) {
super.fireEventForUnrestrictedListeners(event);
}
diff --git a/src/main/resources/Documentation/config.md b/src/main/resources/Documentation/config.md
index 377626d..1440e0b 100644
--- a/src/main/resources/Documentation/config.md
+++ b/src/main/resources/Documentation/config.md
@@ -236,3 +236,23 @@
```healthcheck.enable```
: Whether to enable the health check endpoint. Defaults to 'true'.
+
+File 'gerrit.config'
+--------------------
+
+```gerrit.instanceId```
+: Optional identifier for this Gerrit instance.
+[[docs](https://gerrit-documentation.storage.googleapis.com/Documentation/3.2.0/config-gerrit.html#gerrit.instanceId)].
+
+Whilst this is not, specifically, a high-availability plugin configuration, it plays
+an important role on which events are forwarded to peers.
+
+If `instanceId` is set, events produced by that Gerrit instance will contain its
+origin in the `instanceId` field, allowing to track where they are coming from.
+
+The high-availability plugin will check the `instanceId` value to decide whether
+an event should be forwarded: events that originated from different Gerrit instances
+will not be forwarded.
+
+When neither `gerrit.instanceId` nor `event.instanceId` are set, it is not possible
+to identify the origin of the event and thus the event is always forwarded.
diff --git a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedAwareEventBrokerTest.java b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedAwareEventBrokerTest.java
index ec5b1de..cfe0475 100644
--- a/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedAwareEventBrokerTest.java
+++ b/src/test/java/com/ericsson/gerrit/plugins/highavailability/forwarder/ForwardedAwareEventBrokerTest.java
@@ -30,7 +30,9 @@
private EventListener listenerMock;
private ForwardedAwareEventBroker broker;
- private Event event = new TestEvent();
+ private ForwardedAwareEventBroker brokerWithGerritInstanceId;
+ private Event event;
+ private String gerritInstanceId = "gerrit-instance-id";
@Before
public void setUp() {
@@ -38,8 +40,11 @@
listenerMock = mock(EventListener.class);
DynamicSet<EventListener> set = DynamicSet.emptySet();
set.add("high-availability", listenerMock);
+ event = new TestEvent();
PluginSetContext<EventListener> listeners = new PluginSetContext<>(set, mockMetrics);
broker = new ForwardedAwareEventBroker(null, listeners, null, null, null, null);
+ brokerWithGerritInstanceId =
+ new ForwardedAwareEventBroker(null, listeners, null, null, null, gerritInstanceId);
}
@Test
@@ -58,4 +63,43 @@
}
verifyZeroInteractions(listenerMock);
}
+
+ @Test
+ public void shouldNotDispatchEventWhenEventInstanceIdIsDefinedButGerritInstanceIdIsNot() {
+ event.instanceId = gerritInstanceId;
+ try {
+ broker.fireEventForUnrestrictedListeners(event);
+ } finally {
+ Context.unsetForwardedEvent();
+ }
+ verifyZeroInteractions(listenerMock);
+ }
+
+ @Test
+ public void shouldNotDispatchEventWhenGerritInstanceIdIsDefinedButEventInstanceIdIsNot() {
+ try {
+ brokerWithGerritInstanceId.fireEventForUnrestrictedListeners(event);
+ } finally {
+ Context.unsetForwardedEvent();
+ }
+ verifyZeroInteractions(listenerMock);
+ }
+
+ @Test
+ public void shouldNotDispatchEventWhenInstanceIdsAreDifferent() {
+ event.instanceId = "some-other-gerrit-instance-id";
+ try {
+ brokerWithGerritInstanceId.fireEventForUnrestrictedListeners(event);
+ } finally {
+ Context.unsetForwardedEvent();
+ }
+ verifyZeroInteractions(listenerMock);
+ }
+
+ @Test
+ public void shouldDispatchEventWhenInstanceIdsAreEqual() {
+ event.instanceId = gerritInstanceId;
+ brokerWithGerritInstanceId.fireEventForUnrestrictedListeners(event);
+ verify(listenerMock).onEvent(event);
+ }
}