Overview
The proposed solution would be having a dedicated configuration (i.e.: instanceId
)
used to identify the instance.
Implementation
Setup
The instanceId
could be added in the gerrit.config
under the gerrit
section.
It could be automatically initialised when not present at service startup,
similarly to how the serverId
is generated today.
The id could be a UUIDv4 to avoid the need of a central authority for the generation of a unique ID.
Propagation
Each event will need to be labelled with the instanceId
it has been
generated from.
The com.google.gerrit.server.events.Event
will need to be modified to accommodate
the new parameter.
Exposing the identifier
Gerrit will have to expose the local instanceId
so plugins can use it.
This can be done with a new @InstanceId annotation.
Current consumers compatibility
Gerrit Jenkins Trigger Plugin
The addition of an instanceId
in the Events won’t affect the Gerrit Jenkins
Trigger Plugin, since the DTO used is really lax and decoupled from Gerrit.
Additional fields added to the Event will just be ignored.
Other plugins
I used this query
and this other one
to assess the plugins that might be impacted by the change of the
com.google.gerrit.server.events.Event
.
Plugins that would need adaptation with this change will be the
multi-site and the events-broker since they will have to start using the core
instanceId
instead of the multi-site definition of instanceId
.
The events-log plugin, used for example by the Gerrit Jenkins Trigger Plugin, might also need extra work to store the extra field in the database. A database schema migration will also be needed.
The high-availability won’t need to be modified, but there will be the chance of simplifying it and make it more resilient, since it won’t have to store the forwarded events in the thread local storage anymore.
Use case fulfilment
This solution would satisfy the use cases presented in the description of the problem.
Having the instanceId
will allow to inspect the event payload to understand its origin.
Let’s analyse the by-products:
- Avoid loops: events with the same
instanceId
of the consuming instance can be filtered out, avoiding creation of loops. Plugins like thehigh-availability
can be simplified avoiding to store in memory the forwarded events to keep track of the origin. - Priority routing: logic can be implemented around
instanceId
of an event to decide which one to consume first depending on its origin. Discoverability of the other instances in the cluster is not part of this work. - Troubleshooting:
instanceId
can be dumped in log if needed. This is already possible only the extra field will be present as well. - Preventing events duplication: if we take the case of the Slack plugin, notifications
can be sent only from the instance producing the event
(i.e.:
instanceId
of the event ==instanceId
of the Gerrit instance). This will prevent multiple notifications. This scenario is the dual of the first one, Avoid loops. In this case instance producing an event wants to perform some operations when consuming it, in the other case we just want a no-ops.