Instead of iterating over all publications currently in progress we now use a map to look them up by key.
Baseline
--------
Benchmark Mode Cnt Score Error Units
….inProgressPublicationsAccess thrpt 50 312,155 ± 7,428 ops/s
Fixed
-----
Benchmark Mode Cnt Score Error Units
….inProgressPublicationsAccess thrpt 50 2328732,504 ± 7809,092 ops/s
Before this commit the code resubmitting incomplete event publications unregistered them independently of whether they succeeded or not. We now only do that for failed submissions as an error here indicates a failure to *submit* the publication. As the execution is likely performed asynchronously, a successful hand-off does not implicate the publication being completely processed.
We now rather use an object identity comparison in TargetEventPublication.isAssociatedWith(…) instead of an ….equals(…) as that would return the wrong publication for identical events.
We now support an archiving completion mode that copies the entry to be completed into a dedicated archive to retain the completed event publications but also keep the main publication store small for more efficient data access.
Co-authored-by: Oliver Drotbohm <oliver.drotbohm@broadcom.com>
DefaultEventPublicationRegistry.processIncompletePublications(…) now actively unregisters the publication from being considered in progress after completion (either successful or failed). While CompletionRegisteringAdvisor should take care of that on the target listeners we now leave the publications in progress in consistent state independent of the actual target being invoked. Decrease log level of the failed listener invocation as it's not unusual for the listener to fail.
Improved PublicationsInProgress by switching to a concurrent map internally to avoid ConcurrentModificationExceptions in case of multiple threads.
We now support SpEL expressions in routing targets for events to be externalized. Introduced a BrokerRouting.getTarget(Object) overload to allow access to the event object in the SpEL expression. To support those, event externalizers will have to call that method where they previously called ….getTarget().
We now use the ability to override transaction propagation introduce for GH-858 to tweak the application module listener declaration on DelegatingEventListener so that we do not create a transaction by default. This avoids a database connection being acquired as the listener is very likely to interact with a non-transactional resource anyway.
We now expose a spring.modulith.events.completion-mode property, defaulting the previous behavior to a value of UPDATE. The property can also be configured to DELETE, which will cause the persistence implementations to flip to removing the database entries for event publications instead of setting the completion date.
DefaultEventPublicationRegistry now tracks the event publications currently in progress, so that the completion step can use the database identifier to issue an update statement solely based on that.