Releases: cloudcreate-dk/essentials-project
Release list
Release 0.40.24 Spring Boot 3.3.*
What's Changed
- Queue improvements - release 0.40.24 by @cloudcreate-dk in #118
Full Changelog: 0.40.23...0.40.24
Release Notes Summary
🚨 Important Defaults and Potential Breaking Changes
- Upgraded to Spring Boot 3.3.* - the last version compatible with Spring Boot 3.2 is version 0.40.23
- Centralized Message Fetcher for PostgreSQL durable queues is enabled by default in Spring-Boot starters. Adjust or disable explicitly if not required.
- EventProcessor now extends
AbstractEventProcessor. Please report any backwards compatibility issues!
🚀 New Features
PostgreSQL Durable Queues
-
Centralized Message Fetcher: Introduced a single-threaded polling mechanism (
CentralizedMessageFetcher) to reduce DB load by distributing tasks to worker threads.- Configurable via
essentials.durable-queues.use-centralized-message-fetcher(default: enabled) andessentials.durable-queues.centralized-message-fetcher-polling-interval(default: 20 ms). - New integration tests:
CentralizedFetcherDurableQueueIT.
- Configurable via
-
New method:
hasOrderedMessageQueuedForKeyfor message inspection.
Event Processing and Subscription
-
ViewEventProcessor (Experimental):
- Direct processing of
PersistedEvents; fallback to durable queues on processing errors.ViewEventProcessoris an abstraction for processing events that are projected into views (e.g. in a relational database).- It integrates with a distributed locking mechanism to ensure exclusive access during processing.
PersistedEvent's are processed directly and only in case of an error handling the event will this event (and later events associated with the same aggregate id) be queued onto the underlying durable queue associated with this processor.
- Direct processing of
-
Enhanced subscription management via asynchronous methods:
subscribeToAggregateEventsAsynchronouslyand improved reset handling.- Batch subscription (
batchSubscribeToAggregateEventsAsynchronously) introduced for increased throughput with retries and improved error handling:BatchedPersistedEventHandlersupports receiving multiple Events in a batch.
🛠️ Refactoring & Improvements
- Improved integration tests for PostgreSQL durable queues:
- Standardized visibility and abstracted common test logic.
- Refined implementations of
equals,hashCodeinMessageMetaData, and improved documentation across multiple classes. - Handling
SQLTransientExceptionnow supported inIOExceptionUtil. - Graceful handling (
Flux.empty()) when listener closure fails inListenNotify.
📚 Documentation
- Documented new properties for centralized message fetching in READMEs.
📦 Dependency Updates
-
Kotlin:
2.0.21→2.1.20 -
Spring Boot:
3.2.12→3.3.11 -
Spring Framework BOM:
6.1.18→6.1.19 -
Reactor BOM:
2023.0.16→2023.0.17 -
Spring Data MongoDB:
4.2.12→4.3.11 -
Spring Data JPA:
3.2.12→3.3.11 -
MongoDB Driver Sync:
4.11.5→5.0.1 -
SnakeYAML:
2.3→2.4 -
Micrometer:
1.12.13→1.13.13 -
Micrometer Tracing:
1.2.12→1.3.11 -
Netty BOM:
4.1.119.Final→4.2.0.Final -
JUnit BOM:
5.12.1→5.12.2 -
Testcontainers BOM:
1.20.6→1.21.0 -
JDBI3 BOM:
3.49.0→3.49.3 -
Jackson BOM:
2.18.3→2.19.0 -
Mockito BOM:
5.16.1→5.17.0 -
Removed unnecessary Tomcat dependencies.
Release 0.40.23 Spring Boot 3.2.*
What's Changed
- Release 0.40.23 by @cloudcreate-dk in #117
🚀 Release Highlights – v0.40.23
This release brings major improvements across observability, error handling, configuration, MongoDB integration, and internal architecture — now grouped for clarity.
🏢 Project Metadata
- Updated project
organizationto Trustworks - Updated project
organizationUrlto https://www.trustworks.dk
This will soon become the new home for the project
🧠 metrics
- Introduced the
MeasurementTakerAPI for pluggable performance tracking- Includes
LoggingMeasurementRecorderandMicrometerMeasurementRecorder
- Includes
- Added support for per-subsystem execution time thresholds via configuration
- Introduced:
RecordExecutionTimeCommandBusInterceptorRecordExecutionTimeDurableQueueInterceptorRecordExecutionTimeMessageHandlerInterceptorRecordExecutionTimeEventStoreInterceptor
- Logging can be configured for each interceptor with class-specific logger names
- Most new properties to control metrics collection under
essentials.metrics.*, others are underessentials.eventstore
📦 durable-queues
- Introduced
DurableQueueDeserializationException DefaultDurableQueueConsumer:- Immediately marks failed deserialization messages as Dead-Letter-Messages
- Supports new
HandleQueuedMessageinterceptor operation
- Updated:
PostgresqlDurableQueues.getNextMessageReadyForDeliveryMongoDurableQueues.getNextMessageReadyForDelivery
- Added
RecordExecutionTimeDurableQueueInterceptor - Expanded
DurableQueuesITto test dead-letter behavior on deserialization failure
🧰 eventstore-postgresql
- Introduced
EventStoreSubscriptionObserverinterface - Added
MeasurementEventStoreSubscriptionObserverfor trackingEventStoreSubscriptiondelivery duration DefaultEventStoreSubscriptionManagernow usesMeasurementEventStoreSubscriptionObserverby default- Added:
RecordExecutionTimeEventStoreInterceptorfor performance tracking
- Improved:
- Logging and exception description for
OptimisticAppendToStreamExceptionandAppendToStreamException PollEventStoreTaskpoll logic to adapt to publishing activity- Handling of
resolveBatchSizeForThisQueryedge case
- Logging and exception description for
🧱 eventsourced-aggregates
- Improved logging in
DefaultStatefulAggregateRepository- Changed default log level from
TRACEtoDEBUG
- Changed default log level from
🔐 Mongo fenced-locking
- Improved
MongoFencedLockStoragehandling ofTransactionExceptionandWriteConflictscenarios - Introduced
MongoUtil.isWriteConflictand reused it across:MongoFencedLockStorageMongoDurableQueues
- Adjusted
DBFencedLockManagerITfor improved reliability under concurrency and connectivity issues- Improved reconnection timing logic for stability
🛠 unit-of-work
UnitOfWorkFactoryandUnitOfWorkLifecycleCallbacknow useThrowableinstead ofExceptionfor broader rollback coverage- Unified error handling logic:
UnitOfWorkFactory.usingUnitOfWorknow aligns withUnitOfWorkFactory.withUnitOfWorkfor consistent rollback behavior
SpringTransactionAwareUnitOfWorkFactoryimproved to correctly handleTransactionSynchronization.STATUS_UNKNOWN
🔄 command-handling
- Introduced
RecordExecutionTimeCommandBusInterceptor - Default bean name changed from
commandBustoessentialsCommandBusforDurableLocalCommandBus - Improved bean configuration and auto-wiring consistency
📨 event-bus and messaging
- Introduced
RecordExecutionTimeMessageHandlerInterceptor - Default bean name changed from
eventBustoessentialsEventBusforEventBus - Improved
EventProcessorlogging - Introduced
InfrastructureLocalEventBusfor technical/internal events
⚙️spring-starters
- Added support for disabling
ReactiveHandlersBeanPostProcessorviaessentials.reactive-bean-post-processor-enabled ReactiveHandlersBeanPostProcessornow ignores:- Beans with
@AutoConfiguration - Beans with role
BeanDefinition.ROLE_INFRASTRUCTURE
- Beans with
🧬 Module: essentials-types & essentials-types-jackson
- Enhanced Jackson 2.18 compatibility:
AggregateType,EventName,EventType,CorrelationId,EventId,MessageId,SubscriberId,TenantIdCharSequenceType,CountryCode,CurrencyCode,EmailAddressInboxName,LockName,OutboxName,QueueEntryId,QueueName
- Improved documentation in both modules’
README.mdfiles
🧠 Module: shared
- Introduced:
QuadFunction: a generic 4-arg functional interfaceInvocationTracker: for tracking method execution viaPatternMatchingMethodInvokerFunctionalInterfaceLoggingNameResolver: for logging-friendly names from lambdas and method references
📚 Kotlin event-sourcing
- Added Kotlin doc examples to
GivenWhenThenScenario
📦 Dependency & Plugin Updates (All Modules)
- Upgraded core dependencies:
- Spring Framework, Reactor, Netty, SLF4J, Jackson, JUnit, Mockito, Testcontainers, Awaitility, JDBI
- Security: upgraded Tomcat to 10.1.39 to resolve CVE in 10.1.33 (included with Spring Boot 3.2.12)
- Maven Plugin upgrades:
maven-compiler-plugin,maven-surefire-plugin,dependency-check-maven, and more
Full Changelog: 0.40.22...0.40.23
All changes:
- Updated the project's
organizationandorganizationUrltoTrustworksandhttps://www.trustworks.dkas this will become the new home for the project - Updated 3rd party dependencies:
- spring-framework 6.1.18
- reactor 2023.0.16
- slf4j 2.0.17
- awaitility 4.3.0
- netty 4.1.119.Final
- junit 5.12.1
- testcontainers 1.20.6
- jdbi3 3.49.0
- jackson 2.18.3
- mockito 5.16.1
- logback 1.5.18
- tomcat 10.1.39 (Due to CVE in version 10.1.33 included by Spring Boot 3.2.12)
- Updated maven plugins:
- maven-project-info-reports-plugin 3.9.0
- maven-clean-plugin 3.4.1
- maven-install-plugin 3.1.4
- maven-deploy-plugin 3.1.4
- maven-failsafe-plugin / maven-surefire-plugin 3.5.3
- maven-compiler-plugin 3.14.0
- dependency-check-maven 12.1.1
- flatten-maven-plugin 1.7.0
- Added configuration of
MeasurementEventStoreSubscriptionObserverandRecordExecutionTimeEventStoreInterceptorwhich can be configured using these properties:-
# Event Store metrics configuration essentials.event-store.metrics.enabled=true essentials.event-store.metrics.thresholds.debug=25ms essentials.event-store.metrics.thresholds.info=200ms essentials.event-store.metrics.thresholds.warn=500ms essentials.event-store.metrics.thresholds.error=5000ms essentials.event-store.subscription-manager.metrics.enabled=true essentials.event-store.subscription-manager.metrics.thresholds.debug=25ms essentials.event-store.subscription-manager.metrics.thresholds.info=200ms essentials.event-store.subscription-manager.metrics.thresholds.warn=500ms essentials.event-store.subscription-manager.metrics.thresholds.error=5000ms - and logging can be configured using
<logger name="dk.cloudcreate.essentials.components.eventsourced.eventstore.postgresql.observability.micrometer.MeasurementEventStoreSubscriptionObserver" level="DEBUG"/> <logger name="dk.cloudcreate.essentials.components.eventsourced.eventstore.postgresql.interceptor.micrometer.RecordExecutionTimeEventStoreInterceptor" level="DEBUG"/>
-
- Introduced
essentials.reactive-bean-post-processor-enabledto disable theReactiveHandlersBeanPostProcessor - Changed default bean name:
essentialsCommandBusinstead ofcommandBusforDurableLocalCommandBusessentialsEventBusinstead ofeventBusforEventBus
- Auto configuration of
RecordExecutionTimeMessageHandlerInterceptor,RecordExecutionTimeCommandBusInterceptorandRecordExecutionTimeDurableQueueInterceptorfor essentials metrics collection and logging- Performance tracking is not enabled per default
- To enable tracking and controlling logging you can use
and logging levels using:# Durable Queues metrics configuration essentials.metrics.durable-queues.enabled=true essentials.metrics.durable-queues.thresholds.debug=25ms essentials.metrics.durable-queues.thresholds.info=200ms essentials.metrics.durable-queues.thresholds.warn=500ms essentials.metrics.durable-queues.thresholds.error=5000ms # Command Bus metrics configuration essentials.metrics.command-bus.enabled=true essentials.metrics.command-bus.thresholds.debug=25ms essentials.metrics.command-bus.thresholds.info=200ms essentials.metrics.command-bus.thresholds.warn=500ms essentials.metrics.command-bus.thresholds.error=5000ms # Message Handler metrics configuration essentials.metrics.message-handler.enabled=true essentials.metrics.message-handler.thresholds.debug=25ms essentials.metrics.message-handler.thresholds.info=200ms essentials.metrics.message-handler.thresholds.warn=500ms essentials.metrics.message-handler.thresholds.error=5000ms
<logger name="dk.cloudcreate.essentials.components.foundation.interceptor.micrometer.RecordExecutionTimeCommandBusInterceptor" level="DEBUG"/> <logger name="dk.cloudcreate.essentials.components.foundation.interceptor.micrometer.RecordExecutionTimeDurableQueueInterceptor" level="DEBUG"/> <logger name="dk.cloudcreate.essentials.components.foundation.interceptor.micrometer.RecordExecutionTimeMessageHandlerInterceptor" level="DEBUG"/>
- Expanded `Dur...
Release 0.40.22 Spring Boot 3.2.*
What's Changed
- Error handling improvements by @cloudcreate-dk in #114
- ability to register event processors that starts consuming from the last event by @AndersHelmar in #115
- Release 0.40.22 by @cloudcreate-dk in #116
Full Changelog: 0.40.21...0.40.22
- Added ability to register
EventProcessor's that always starts consuming from the lastest event - Improved
CommandBus/DurableLocalCommandBusdocumentation and Spring configuration ofRedeliveryPolicy/SendAndDontWaitErrorHandler - Introduced new
Exceptionsmethods which are used by code that catchesThrowableto avoid suppressing unrecoverable errors (such asVirtualMachineError) that should not be caught/handled by framework logic:rethrowIfCriticalErrorisCriticalError
DBFencedLockManagerintegration tests now performdeleteAllLocksInDBprior to starting the lock manager nodes- Added
Exceptions.rethrowIfCriticalError/isCriticalErrorchecks whereThrowableis caught - Improved
DBFencedLockManager's cleanup logic/logging and reporting in case a lock couldn't be confirmed- Added
Exceptions.rethrowIfCriticalErrorwhereThrowableis caught
- Added
MultiTableChangeListener- Improved javadoc
- Now implements
Lifecycle - Improved cleanup logic/logging
- Added
Exceptions.rethrowIfCriticalErrorwhereThrowableis caught
- Added information about default property values in
EventStoreSubscriptionManagerBuilder - Improved
DefaultEventStoreSubscriptionManager's cleanup logic/logging- Changed saveResumePoints scheduled process thread name to start with
EventStoreSubscriptionManager-SaveResumePoints- - Added
Exceptions.rethrowIfCriticalErrorwhereThrowableis caught onErrorHandlingEventnow accepts aThrowableinstead of anException
- Changed saveResumePoints scheduled process thread name to start with
- Added
EventProcessorintegration test - Added more logging to
DurableLocalCommandBus - Corrected the event published from
DBFencedLockManagerstartto beFencedLockManagerStarted - Adjusted default
EventProcessor.getNumberOfParallelInboxMessageConsumersto 1 instead of the number of available CPU processors ! - Changed to
CopyOnWriteArrayListinLocalEventBusTest'sBlockingEventHandlerto avoid potentialConcurrentModificationException - Added parallelization for
maven-surefire-pluginandmaven-failsafe-plugin
Updated 3rd party dependencies:
- Spring 6.1.17
- Reactor 2023.0.15
- Json-Smart 2.5.2
- Netty 4.1.118.Final
- Jdbi 3.48.0
Updated Maven plugins:
- dependency-check-maven 12.1.0
Release 0.40.21 Spring Boot 3.2.*
What's Changed
- only report queue sizes to micrometer if the queue is active on the instance by @AndersHelmar in #110
- Release 0.40.21 by @cloudcreate-dk in #112
Full Changelog: 0.40.20...0.40.21
- Improved
sharedmodule documentation - Improved
EventProcessorandInTransactionEventProcessorJavaDoc EventStore'sstartStreamnow callsappendToStreamwithNO_EVENTS_PREVIOUSLY_PERSISTED(-1) asappendEventsAfterEventOrdervalue to ensure thatstartStreamonly can be used to start a new aggregate event-stream- Refined
SendAndDontWaitErrorHandlerdocumentation - Refined
SendAndDontWaitErrorHandlerdocumentation in the context ofDurableLocalCommandBusBuilder - Added
IOExceptionUtil.isIOExceptionchecks toDBFencedLockManager.stop - Added more assertions to
MessageDeliveryErrorHandlerBuilderTest MultiTableChangeListenerstop: Added additional try/catch aroundscheduledFuture.canceland an explicit call toexecutorService.shutdownNowpollForNotifications: Added additionalscheduledFuturechecks to skip polling early
- Added
spring-webtest dependency DurableQueues: Formatted code and organized importsPostgresqlDurableQueues:- Formatted code and organized imports
- Added additional
IOExceptionUtil.isIOExceptionduringstop - Removed interception of
ConsumeFromQueueandStopConsumingFromQueueinSingleOperationTransactionDurableQueuesInterceptoras they don't require to be run in aUnitOfWork
MongoDurableQueues:- Formatted code and organized imports
- Added additional
IOExceptionUtil.isIOExceptionduringstop
- Aligned log level to
DEBUGfor all log statements logged whenIOExceptionUtil.isIOExceptionreturns true - Updated dependency-check-maven to 12.0.2
Release 0.40.20 Spring Boot 3.2.*
What's Changed
- Release 0.40.20 by @cloudcreate-dk in #109
Full Changelog: 0.40.19...0.40.20
- Added additional
isIOExceptioncheck toDBFencedLockManagerto reduce logging severity in case of IO issues - Allowed
DBFencedLockManager.acquireLockAsyncto be performed without theDBFencedLockManagerhaving been started - Added additional
isIOExceptioncheck toMultiTableChangeListener.unlistento reduce logging severity in case of IO issues - Added more
IOExceptionUtil.isIOExceptionchecks toListenNotifyandMultiTableChangeListener - Added a
toStringmethod to the class returned fromQueuePollingOptimizer.None() - Added additional
isIOExceptioncheck toDefaultDurableQueueConsumerto reduce logging severity in case of IO issues - Added
DurableQueueConsumer.consumerName()method - Improved
DurableQueueBasedInboxandDurableQueueBasedOutboxlogging - Added additional
isIOExceptioncheck toPostgresqlDurableSubscriptionRepository.saveResumePointsto reduce logging severity in case of IO issues - Added additional logging to
PostgresqlDurableQueues.consumeFromQueueandMongoDurableQueues.consumeFromQueue - Switched from using
ArrayListto usingCopyOnWriteArrayListfor the list of interceptors - Changed
DefaultLifecycleManagerto use theSmartLifecycleto attempt to start EssentialsLifecyclebeans AFTER other resources, such as DataSource, has been started; as well as stopLifecycleBeans are stopped prior other resources - Refined the
IOExceptionUtil.isIOExceptionmethod
- Generalized many of the special cases into the following logic:
- Exception or its Root-Cause is a subclass ofIOException
- The Exception's message contains a known error messages across Jdbi, JPA, JDBC, Mongo
- If the exception's causal chain contains an exception that is either a subclass ofConnectionExceptionor a subclass ofMongoSocketException
- Removed checks fororg.jdbi.v3.core.statement.UnableToExecuteStatementException- please report back if this is an issue
- AddedIOExceptionUtilTestinfoundation,postgresql-queueandspringdata-mongo-queue - Refined
Exceptions.getRootCause
- AddedExceptionsTest - Added support for
QueuedMessage.markForRedeliveryIn(Duration deliveryDelay)
- MadecauseForRetryinDurableQueues.retryMessageoptional - Clarified
RedeliveryPolicy.isPermanentErrorarguments - Clarified
MessageDeliveryErrorHandler.isPermanentErrorarguments
- AdjustedMessageDeliveryErrorHandler.StopRedeliveryOn'sisPermanentErrorto use the newExceptions.doesStackTraceContainExceptionOfTypemethod
- AdjustedMessageDeliveryErrorHandlerBuilder.shouldAlwaysRetryOnlogic to use the newExceptions.doesStackTraceContainExceptionOfTypemethod PostgresqlDurableQueues
- Switched to useInstant.now()instead ofOffsetDateTime.now(Clock.systemUTC())
- Added null handling for getCauseForRetry()MongoDurableQueues
- Added null handling for getCauseForRetry()- Updated copyright year
Updated 3rd party dependencies:
- spring-framework 6.1.16
- log4j 2.24.3
- junit 5.11.4
- jackson 2.28.2
- mockito 5.15.2
- logback 1.5.16
- reactor 2023.0.14
- assertj 3.27.3
- postgresql 42.7.5
- netty 4.1.117.Final
Updated maven plugins:
- dokka 2.0.0
- maven-project-info-reports-plugin 3.8.0
- maven-site-plugin 3.21.0
- maven-javadoc-plugin 3.11.2
- dependency-check-maven 12.0.1
Release 0.40.19 Spring Boot 3.2.*
What's Changed
- Ability to add multiple inbox messages in one go by @AndersHelmar in #102
- Release 0.40.19 by @cloudcreate-dk in #103
Full Changelog: 0.40.18...0.40.19
There are many changes in this release, please test thoroughly and provide feedback if you experience any issues.
- Updated queue gauge value on message handled
- Added ability to add multiple messages to an
Inboxat once - Refined Javadoc for
Inbox/OutboxandInboxes/Outboxes - Added ability to add multiple messages to an
Outboxat once (AddedsendMessageListandsendMessagestoOutbox) - Added integration test using a combination of
InTransactionEventProcessorandStatefulAggregateRepositoryto verify that theStatefulAggregateRepositoryUnitOfWorkLifecycleCallback'sbeforeCommitlogic, in combination withGenericHandleAwareUnitOfWorkFactory'sbeforeCommitlogic, allows synchronousEventBusEventHandler's to participate in persisting additional event(s) as part of the sameUnitOfWork - Added a default
fencedLocksTableNamevalue toPostgresqlFencedLockManagerBuilder - Added an
elapsedmethod toStopWatch - Added
filterDuplicateNotificationsto theMultiTableChangeListenerPropertiesin thespring-boot-starter-postgresqlautoconfiguration properties (adjustedREADME.mdto reflect this)
- This is related to the newNotificationDuplicationFilterconcept supported by theMultiTableChangeListener - Added
commandBusParallelSendAndDontWaitConsumersto theReactivePropertiesin thespring-boot-starter-postgresqlandspring-boot-starter-mongodbautoconfiguration properties (adjustedREADME.mdto reflect this)- Renamed
parallelThreadstoeventBusParallelThreadsin theReactiveProperties(adjustedREADME.mdto reflect this)
- Renamed
- Refined the javadoc and clarified
UnitOfWorkhandling forEventStoreEventBus,EventProcessor,InTransactionEventProcessor,EventStoreSubscriptionManager - Refined the
UnitOfWorkLifecycleCallback.BeforeCommitProcessingStatusprocessing status logic inGenericHandleAwareUnitOfWorkFactoryandSpringTransactionAwareUnitOfWorkFactoryso it supports having multiple unitOfWorkLifecycleCallbackResources - Improved
SimpleQueuePollingOptimizerpolling skip logic by switching fromThreadLocaltoAtomicLongsince multiple threads can be involved. - Improved
DefaultDurableQueueConsumer
- AddeduncaughtExceptionHandlerto the polling scheduler
- Added more TRACE logging topollQueue
- ChangedprocessNextMessageReadyForDeliverylogic - Changed default
parallelSendAndDontWaitConsumersvalue forDurableLocalCommandBusfrom 10 to the number of available processors - Introduced
NotificationFilterChain+NotificationDuplicationFiltertoMultiTableChangeListenerwhich can reduce notification load for nearly identical notifications, where the difference isn't important to the listener.
- If two or moreNotification's in a given poll batch share the same duplication key, then only one of them will be published to the listeners registered with theMultiTableChangeListener
- Example: if 100 messages are queued for the sameQueueNamein the sameUnitOfWork, then theMultiTableChangeListenerwill notify
thePostgresqlDurableQueueswith 100TableChangeNotification's. Using theQueueNameDuplicationFilter, thePostgresqlDurableQueues
will only receive a singleTableChangeNotificationfor that specificQueueName. Filtering is only performed on Notifications
returned in a single database notification poll - Added
QueueNameDuplicationFiltertoPostgresqlDurableQueuessetup to reduce notification load when multiple messages are queued for the sameQueueNamewithin a short amount of time (e.g. within a singleUnitOfWork) - Optimized
PostgresqlDurableQueuesindexes to reduce index update time when inserting a lot of messages in a short amount of time - Added
DurableQueuesLoadITto test adding a lot of message within a single UnitOfWork doesn't delay message consumption due to slow index updates - Added more logging to
PostgresqlDurableQueues.getNextMessageReadyForDeliveryand switched to using multiline string - Improved
StatefulAggregateRepositorylogging - Added
isActivetoEventProcessorandInTransactionEventProcessor - Added more
UnitOfWork.infologging
-ExclusiveInTransactionSubscription#isActivenow returnsactiveinstead ofstarted
- Refined javadoc forEssentialsComponentsProperties
Release 0.40.18 Spring Boot 3.2.*
What's Changed
- Release 0.40.18 by @cloudcreate-dk in #101
Full Changelog: 0.40.17...0.40.18
- Clarified
Inbox/OutboxUnitOfWork/transaction handling - Improved lag logging in
SubscriberGlobalOrderMicrometerMonitor - All
Classes.forNamenow use a classloader when converting Fully Qualified Java Class names to Class instances. - Added
getClassLoaderandsetClassLoadertoJSONSerializerto encapsulate setting the class loader on the underlying JSON serializer implementation. - Added new methods to
AggregateEventStreamPersistenceStrategyresolveGlobalEventOrderSequenceNamefindLowestGlobalEventOrderPersisted
- Added
EventStore#findLowestGlobalEventOrderPersisted(AggregateType) PostgresqlDurableSubscriptionRepository- Added
EventStorea constructor argument - Removed
HandleAwareUnitOfWorkFactory<?> unitOfWorkFactoryargument fromPostgresqlDurableSubscriptionRepository, which acquires theHandleAwareUnitOfWorkFactoryfrom theEventStore createResumePointnow usesEventStore.findLowestGlobalEventOrderPersistedto lookup the lowestGlobalEventOrderpersisted and uses this value if it's greater than the providedonFirstSubscriptionSubscribeFromAndIncludingGlobalOrder(which typically defaults toGlobalEventOrder#FIRST_GLOBAL_EVENT_ORDER)- This solves an issue where (Re)Subscriptions after the EventStream table(s) have been truncated, but the corresponding
GlobalEventOrdersequence hasn't been reset, would result in a slow catchup towards the lowest persistedGlobalEventOrder, due to EventStream Gap detection being cautious with regards to how fast Subscriptions increase the global-event-order range that's included in EventStore polling requests.
- This solves an issue where (Re)Subscriptions after the EventStream table(s) have been truncated, but the corresponding
- Added
- Switched to use log-level
DEBUGforSqlExecutionTimeLogger.logException, instead of levelERROR - Improved
PostgresqlEventStreamGapHandlerlog output - Improved the
OptimisticAppendToStreamExceptiondetection inSeparateTablePerAggregateTypePersistenceStrategyand removed the cause exception fromOptimisticAppendToStreamExceptionandAppendToStreamException - Improved
OptimisticAppendToStreamExceptiontesting inSingleTenantPostgresqlEventStoreIT - Improved EventJSON, EventMetaDataJSON, EventMetaData and PersistedEvent - added unit tests
- Improved
EventStoreSubscriptionManager_subscribeToAggregateEventsAsynchronously_ITtest - Moved
Lifecycleto theSharedmodule - keptLifecycleinFoundationfor backwards compatibility EventBusnow extendsLifecycle- Redesigned the
LocalEventBus- Removed
Optional's from constructors and introduced a Builder - async publisher code, which now has improved Overflow handling. It supports controlling the Flux backpressure buffer size, queue task cap size, overflow max retries
- Improved shutdown logic
- Removed
- Improved
EventStoreEventBus- Removed
Optional's from constructors
- Removed
- Added equals/hashCode/toString to
EventJSONTest - Added
BeforeCommitProcessingStatusreturn value toUnitOfWorkLifecycleCallback#beforeCommitto allowGenericHandleAwareUnitOfWorkFactoryandSpringTransactionAwareEventStoreUnitOfWorkFactoryto rerun the beforeCommit phase to capture aggregate changes resulting from in-transaction event handling (e.g. from code listening to theEventBus) - Changed the
UnitOfWorkLifecycleCallbackinFlexAggregateRepositoryandStatefulAggregateRepositoryto returnBeforeCommitProcessingStatus.REQUIREDas long as each beforeCommit run returns changes to aggregates. - Added
infomethod toUnitOfWork - Added debug logging of
UnitOfWork#infoinUnitOfWorkFactory - Added copying
PersistedEvent's list inPersistedEventssince the associated lists are reset inEventStoreManagedUnitOfWorkacross beforeCommit runs - Adjusted before/after commit callback logic in
SpringTransactionAwareEventStoreUnitOfWorkFactory - Renamed Spring EventStore integration test classes from being called "Test" to "IT"
- Added
ReactivePropertiestoEssentialsComponentsConfigurationto allow controlling theLocalEventBus/EventStoreEventBusproperties - Updated README.md
- Added support for
exclusivelySubscribeToAggregateEventsInTransactioninEventStoreSubscriptionManager(work in progress) - Added
InTransactionEventProcessor(work in progress)
Updated to Kotlin 2.0.21
Updated 3rd party dependencies
- Spring Boot 3.2.12
- Spring Framework 6.1.15
- Reactor 2023.0.12
- Spring Data MongoDB 4.2.12
- Spring Data JPA 3.2.12
- mongodb-driver-sync 4.11.5
- log4j-to-slf4j 2.24.2
- micrometer 1.12.13
- micrometer-tracing 1.2.12
- netty 4.1.115.Final
- JUnit 5.11.3
- TestContainers 1.20.4
- JDBI 3.47.0
- Jackson 2.18.1
- LogBack 1.5.12
Updated Maven plugins
- maven-javadoc-plugin 3.10.1
- maven-dependency-plugin 3.8.1
- maven-failsafe-plugin / maven-surefire-plugin 3.5.2
- versions-maven-plugin 2.18.0
- dependency-check-maven 11.1.0
Release 0.40.17 Spring Boot 3.2.*
What's Changed
- Release 0.40.17 by @cloudcreate-dk in #99
Full Changelog: 0.40.16...0.40.17
- Improved
IOExceptionUtilfurther by using aConcurrentHashMap(to avoidConcurrentModificationException) and defaulting Exception messages that are null to an empty String to avoid potentialNullPointerException's - Improved
IOExceptionUtilfurther by defaulting Root Cause Exception messages that are null to an empty String to avoid potentialNullPointerException's - Introduced
releaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmationconfiguration toDBFencedLockManager, which allows a developer/user to control if aFencedLockacquired by a givenFencedLockManagershould be released in case calls toFencedLockStorage#confirmLockInDB(DBFencedLockManager, UnitOfWork, DBFencedLock, OffsetDateTime)fails with an exception whereIOExceptionUtil#isIOException(Throwable)returns true. IfreleaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmationis true, thenFencedLock's will be released locally,
otherwise we will retain theFencedLock's as locked. - Added
DBFencedLockManager_MultiNode_ReleaseLockIT(and provider specific subclasses) to test locally acquired locks being released ifreleaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmationis true - Improved DBFencedLockManager#confirmAllLocallyAcquiredLocks, DBFencedLockManager#releaseLock, DBFencedLockManager#acquireLockAsync
- Improved PostgresqlFencedLockStorage#updateLockInDB to include the timed-out locks last
lock_last_confirmed_tstimestamp to reduce the risk of two nodes trying to acquire the same lock concurrently - Improved MongoFencedLockStorage#updateLockInDB to include the timed-out locks last
lockLastConfirmedTimestamptimestamp to reduce the risk of two nodes trying to acquire the same lock concurrently - Added
ReleaseAcquiredLocksInCaseOfIOExceptionsDuringLockConfirmationto the FencedLockManager Properties for both the MongoDB and Postgresql SpringBoot starter configuration (default value isfalse) - Expanded documentation related to configuring the fenced lock manager's
release lock in case of IO exceptions during lock confirmationsetting:essentials.fenced-lock-manager.release-acquired-locks-in-case-of-i-o-exceptions-during-lock-confirmation=false
Updated 3rd party dependencies:
- TestContainers 1.20.2
- Mockito 5.14.1
Release 0.40.16 Spring Boot 3.2.*
What's Changed
- Release 0.40.16 by @cloudcreate-dk in #98
Full Changelog: 0.40.15...0.40.16
- Ensured
Typescompatibility with Jackson 2.18.0 by adding explicitString(for subclasses ofCharSequenceType) orNumber(for subclasses ofNumberType) constructors to concrete semantic types - Made providing an Exception optional when marking a
DurableQueuemessage as a dead-letter message - Added support for providing an optional String description/cause when marking a
DurableQueuemessage as dead-letter message - Added test to
DurableQueuesIT, for a case where a Message handler during consumption manually marks the message as a dead-letter message, to confirm that the message is marked as a dead-letter message - Changed
PostgresqlDurableQueues#acknowledgeMessageAsHandled(AcknowledgeMessageAsHandled)to only delete a message if it's NOT marked as a dead-letter message - Changed
MongoDurableQueues#markAsDeadLetterMessage(MarkAsDeadLetterMessage)to not require that the message is marked isisBeingDelivered. The operation now also resetsnextDeliveryTimestampto null. This aligns withPostgresqlDurableQueuesbehaviour - Changed
MongoDurableQueues#acknowledgeMessageAsHandled(AcknowledgeMessageAsHandled)to only delete a message if it's NOT marked as a dead-letter message and not require that the message is marked isisBeingDelivered - Since many operations are initiated by a new
UnitOfWork, theDBFencedLockManager's version ofwithUnitOfWorkandusingUnitOfWorknow requires an error handler to make error handling explicit - The internal
DBFencedLockManager#confirmAllLocallyAcquiredLocksno longer releases locks in case of an IO Exception during call tolockStorage.confirmLockInDB. If DB connectivity is broken it's better to retain the lock ownership as all nodes accessing the DB will likely experience the same behaviour - Added tests to
DBFencedLockManagerIT, therebyPostgresqlFencedLockManagerITandMongoFencedLockManagerIT, that tests the behaviour in case database connectivity is interrupted - Fixed potential
NoClassDefFoundExceptioninIOExceptionUtil - Added tests to
DurableQueueintegration tests to verify the behaviour in case database connectivity is interrupted - Improved
EventStoreSubscriptionjavadoc - Introduced
PersistedEventSubscriberinEventStoreSubscriptionManagerto handle allEventStore#pollEventrelated logic, event forwarding and error handling related to asynchronous subscriptions - Added
EventStoreSubscriptionManagertests that verify behaviour when the database connectivity is interrupted
Updated 3rd party dependencies:
- Spring-Boot 3.2.10
- Spring-Data-MongoDB 4.2.10
- Spring-Data-JPA 3.2.10
- MongoDB Driver Sync 4.11.4
- log4j 2.24.0
- snakeyaml 2.3
- micrometer 1.12.10
- micrometer-tracing 1.2.10
- netty 4.1.113.Final
- Junit 5.11.1
- Jackson 2.18.0
- Reactor 2023.0.10
- Spring 6.1.13
- Mockito 5.14.0
- Logback 1.5.8
Updated maven plugins:
- maven-failsafe-plugin / maven-surefire-plugin 3.5.0
- dependency-check-maven 10.0.4
- maven-gpg-plugin 3.2.7
Release 0.40.15 Spring Boot 3.2.*
What's Changed
- Release 0.40.15 by @cloudcreate-dk in #97
Full Changelog: 0.40.14...0.40.15
- Improved
DefaultDurableQueueConsumermessage handling error logging, plus adjusted behaviour in caseTransactionalMode.FullyTransactionalis used as TransactionalMode - Added
#getObjectMappertoJacksonJSONSerializerto support changes toEssentialsComponentsConfiguration EssentialsComponentsConfiguration: Iforg.springframework.boot:spring-boot-devtoolsis added to the classpath (to support class reloading during development time), then we add support for dynamically changing ClassLoaders, in order to avoidClassCastException's for messages/events/etc. that are deserialized from JSON
- This is done by checked iforg.springframework.boot.devtools.restart.RestartScopeis on the classpath
- In that case theSpringBootDevToolsClassLoaderChangeContextRefreshedListeneris added to theApplicationContextto ensure thatJacksonJSONSerializer#getObjectMapperuses the sameClassLoaderas theApplicationContext
Upgraded 3rd party dependencies
- mockito 5.13.0
Downgraded 3rd party dependencies to retain Spring Boot 3.2.x compatibility:
- micrometer 1.12.9
- micrometer-tracing 1.2.9
Downgraded maven-javadoc-plugin to version 3.7.0 because version 3.8.0 was reporting VM memory errors, such as:
[INFO] The goal 'org.apache.maven.plugins:maven-javadoc-plugin:3.8.0:javadoc' has not been previously called for the module: 'dk.cloudcreate.essentials:types:jar:DEV-SNAPSHOT'. Trying to invoke it...
[ERROR] Error occurred during initialization of VM, trying to use an empty MAVEN_OPTS...
[ERROR] MavenInvocationException: Error occurred during initialization of VM, try to reduce the Java heap size for the MAVEN_OPTS environment variable using -Xms:<size> and -Xmx:<size>.