Events-eiffel plugin listens to ref-updated
for refs/heads/*
to create SCS events, ref-updated
for refs/tags/*
to create tag events and patchset-created
to create SCC.
You can disable event-triggering or configure which refs event creation is triggered for in the All-Project configuration.
The plugin sports a REST API to create missing events manually, also useful if you want to do a “backfill” of historical commits in a controlled fashion before enabling the event-triggered creation of Eiffel events:
The REST APIs are not protected by the same ref-filter that the listeners are, so it should be used with caution. For this reason the REST API endpoints requires the caller to have the ADMINISTRATE_SERVER capability.
Since each parse request potentially can result in walking hundreds of thousand commits and create twice as many Eiffel events (a new branch in the linux kernel would result in ~1.6m events). We need to limit the effect it has on the Gerrit server. The plugin creates it‘s own work queue for incoming parse-requests. Queued parse-requests can be monitored through Gerrit’s show-queue command.
Number of executers used to consume this queue can be configured with EventParsing.poolSize. A reasonable poolsize for a large Gerrit instance should be between 2-4.
For each Eiffel event creation request first we need to ensure that all the event's parents are created. To find missing parent events we need to walk the commit graph until we find a commit that has a corresponding event of the correct type.
Parsing is done with custom commit-walkers src/main/java/com/googlesource/gerrit/plugins/eventseiffel/parsing/CommitsWalker.java
.
These custom commit-walkers use an external state (whether the corresponding Eiffel event is already created or not) to determine when to stop walking. This state is fetched from the EiffelEventHub.
They also make sure to reuse the object database when walking for child events. E.g. when parsing for SCS event creation we must first parse for corresponding SCC as they must be created first. Creating and tearing down an object database once for each event type is computationally costly and uses twice as much memory.
Once we have determined which commits we need to create events for we need to map those commits to an Eiffel event.
com/googlesource/gerrit/plugins/eventseiffel/mapping/EiffelEventMapper.java
You can configure the mapping get values from the commit instead of using the index to find change-data to populate the Eiffel event from by setting EventMapping.useIndex to False
. This gives a noticeable performance increase when doing a backfill of historical events.
For tag-events (Artc and CD) you can set a namespace by configuring EiffelEvent.namespace. This namespace
becomes part of the purl of the Artc data.identity and the data.name of the CD event. See example at: Tag representation (in the example namespace
is set to gerrit-host
).
com/googlesource/gerrit/plugins/eventseiffel/EiffelEventHub.java
The event hub has four different functions:
EiffelEventIdCache
once an event is reported as published and removed from the queue.The thread-safe implementation com/googlesource/gerrit/plugins/eventseiffel/EiffelEventHubImpl.java
is loosely modeled around LinkedBlockingQueue.java adopted for the more complicated data model of Eiffel events.
com/googlesource/gerrit/plugins/eventseiffel/PublishEventWorker.java
The responsibility of the PublishEventWorker
is to take events from the queue and feed them to the EventPublisher
, which in turn is responsible for publishing the events to Eiffel, as well as keeping track of if the publishing was successful
and report back to the Event Hub.
There is currently only one implementation of EiffelEventPublisher. This implementation publishes the event to a RabbitMQ exchange: com/googlesource/gerrit/plugins/eventseiffel/mq/RabbitMqPublisher.java
com/googlesource/gerrit/plugins/eventseiffel/cache/EiffelEventIdCacheImpl.java
The cache uses a persisted LoadingCache and is backed by the implementation of com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EventStorage.java
Currently the only implementation of EventStorage uses: Eiffel GraphQL API and Eiffel GoER.
If you want to use a different EventStorage, e.g. a local DBMS like postgres or similar, you will need to
If you use other means than a RabbitMQ exchange for publishing events to Eiffel, e.g. REMRem or similar, you will need to:
com/googlesource/gerrit/plugins/eventseiffel/eiffel/api/EiffelEventPublisher.java
interface.