We ran into a strange issue where Saga’s wouldn’t start. Our handler has both @StartSaga and @SagaEventHandler, and the first parameter is the payload, however in one of our environments (prod) the saga (usually) didn’t start, and the event didn’t complete processing (checked using MessageMonitor.Callback). After adding the payload type to the @SagaEventHandler, it works.
Is this a know issue, or are we missing something?
I can reliably reproduce this. After triggering the saga, this exception is thrown: 2017-08-31 19:46:38.243 ERROR 1 --- [SagaProcessor-0] o.a.e.TrackingEventProcessor : Processing loop ended due to uncaught exception. Processor pausing. java.lang.StackOverflowError: null at org.jboss.logging.Logger.logf(Logger.java:2397) at org.jboss.logging.DelegatingBasicLogger.tracef(DelegatingBasicLogger.java:124) at org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl.close(ResourceRegistryStandardImpl.java:148) at org.hibernate.resource.jdbc.internal.ResourceRegistryStandardImpl.releaseResources(ResourceRegistryStandardImpl.java:292) at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.afterTransaction(AbstractLogicalConnectionImplementor.java:55) at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.afterTransaction(LogicalConnectionManagedImpl.java:149) at org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl.afterCompletion(LogicalConnectionManagedImpl.java:260) at org.hibernate.resource.jdbc.internal.AbstractLogicalConnectionImplementor.rollback(AbstractLogicalConnectionImplementor.java:122) at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.rollback(JdbcResourceLocalTransactionCoordinatorImpl.java:239) at org.hibernate.engine.transaction.internal.TransactionImpl.rollback(TransactionImpl.java:100) at org.springframework.orm.jpa.JpaTransactionManager.doRollback(JpaTransactionManager.java:544) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processRollback(AbstractPlatformTransactionManager.java:853) at org.springframework.transaction.support.AbstractPlatformTransactionManager.rollback(AbstractPlatformTransactionManager.java:830) at org.axonframework.spring.messaging.unitofwork.SpringTransactionManager.rollbackTransaction(SpringTransactionManager.java:91) at org.axonframework.spring.messaging.unitofwork.SpringTransactionManager$1.rollback(SpringTransactionManager.java:68) at org.axonframework.common.transaction.TransactionManager.fetchInTransaction(TransactionManager.java:71) at org.axonframework.eventsourcing.eventstore.jpa.JpaEventStorageEngine.fetchTrackedEvents(JpaEventStorageEngine.java:149) at org.axonframework.eventsourcing.eventstore.BatchingEventStorageEngine.lambda$readEventData$1(BatchingEventStorageEngine.java:119) at org.axonframework.eventsourcing.eventstore.BatchingEventStorageEngine$EventStreamSpliterator.tryAdvance(BatchingEventStorageEngine.java:157) at java.util.stream.StreamSpliterators$WrappingSpliterator.lambda$initPartialTraversalState$0(StreamSpliterators.java:294) at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.fillBuffer(StreamSpliterators.java:206) at java.util.stream.StreamSpliterators$AbstractWrappingSpliterator.doAdvance(StreamSpliterators.java:161) at java.util.stream.StreamSpliterators$WrappingSpliterator.tryAdvance(StreamSpliterators.java:300) at java.util.Spliterators$1Adapter.hasNext(Spliterators.java:681) at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.peekPrivateStream(EmbeddedEventStore.java:379) at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.peek(EmbeddedEventStore.java:340) at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.peekPrivateStream(EmbeddedEventStore.java:388) at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.peek(EmbeddedEventStore.java:340) at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.peekPrivateStream(EmbeddedEventStore.java:388) at org.axonframework.eventsourcing.eventstore.EmbeddedEventStore$EventConsumer.peek(EmbeddedEventStore.java:340) ... and many more of these ...
After this, sagas don’t trigger. When the app is restarted, those sagas get triggered. If there are no more sagas to process, I can repeat this. Start the app, trigger sagas, until seeing this exception, after which no more sagas will get triggered.
The “peek” stack keeps going until a stack overflow is thrown. After that sagas are no longer triggered. Restarting the app triggers the sagas, but the exception comes up again, stopping saga processing. The first saga is always triggered.
One suggestion there is that it is related to gaps. While gaps should be a very rare thing, in certain databases they are very common. This has to do with the way Hibernate generates sequences. It default to a single sequence generator used for all entities. A solution would be to configure a separate SequenceGenerator for the DomainEventEntry table, which can be done using the given configuration, which should be placed in a META-INF/orm.xml: