Multiple Snapshots within a single Unit Of Work

Hi!

I’ve set the threshold of my EventCountSnapshotTriggerDefinition to 1, for testing purposes. With this setting some of my integration tests fail, which work otherwise perfectly if I use a very high threshold (>25).
One of these tests triggers a Saga that leads to about 19 events on the same aggregate.
Since the threshold is set to 1, every applied event should trigger the creation of a snapshot. The problem I’m facing is that the aggregates are not correctly initialized in the AggregateSnapshotter class. I’ve debugged into
it and it seems that events are published on the aggregate object via the initializeState method but the aggregate object already has the state changes from the event through the previous snapshot. In my case, this
leads to duplicate entries in a list that is stored in the aggregate.

My hunch is that the same UnitOfWork dispatches ‘scheduleSnapshot’ multiple times and therefore could lead to this problems. But unfortunately, this is just a guess.

Do you have an idea what could be the problem and if it’s sufficient for me to set the threshold to a higher value?

I’m also wondering why EventSourcedAggregate.initializeState increases the Snapshot counter when it’s simply rehydrating the aggregate.

Thanks a lot!

Cheers,
Andreas

Hi Andreas,

first of all, please note that a threshold of 25 is not considered very high, in production environments. Usually, I set the value around 100, sometimes even higher, depending on how often aggregates are loaded and how critical the update performance is.
Instead of using a very low trigger threshold, consider using a Cache instead.

However, the behavior you describe is still undesired. It doesn’t really matter how often a snapshot is triggered. The snapshotter will always attempt to create a snapshot with all the events it can retrieve. If it can’t read any (additional) events, it will simply not create the snapshot.
When using snapshots, the first event is usually the aggregate itself, which was stored previously, as a snapshot. From there, all events are applied on that aggregate instance.

To me, it sounds like you may have some weird structure in your aggregate. Can you share the parts where you apply the events that update this list as well as the code for the handler(s) of these events?

Allard

Hi Allard,

thanks for your response. Good to know, I’ll definitely will set the value higher then. Although, the main reason I’m using such a low value is that I wanted to check whether my integration tests are still running with Snapshots.

This is the part where there seems to be a problem:

`

@CommandHandler
public void when(UpdateDatesOnCalendar cmd, MetaData metaData, ClockUtil clockUtil) {
if (isUnavailable()) {
apply(DatesNotSetOnUnavailableCalendar.builder()
.id(id)
.sagaId(cmd.getSagaId())
.build(), metaData);
return;
}

if (isExpiring(clockUtil)) {
apply(CalendarIsExpiring.builder().id(id).build());
}

apply(DatesOnCalendarUpdated.builder()
.id(id)
.sagaId(cmd.getSagaId())
.dates(cmd.getDates())
.removedDates(cmd.getRemovedDates())
.build(), metaData);

if (datesAreDue(cmd.getDates, clockUtil)) {
apply(CalendarIsDue.builder()
.id(id)
.build(), metaData);
}

}

@EventSourcingHandler
public void impose(DatesOnCalendarUpdated evt) {
dates.addAll(evt.getDates());

evt.getRemovedDates().forEach(d -> {
dates.remove(d);
});
}

`

Since the impose method mutates the list ‘dates’, the application of the DatesOnCalendarUpdated event is not idempotent. When I set the Snapshot Threshold to 25 or lower, the event is applied multiple times, leading to duplicate entries in the list. If I set the threshold to a higher value, then the event is only applied once. While debugging it seemed that the duplicate application happened while the aggregate was dehydrated before a new event was applied.

Thanks for all the help and sorry my late post!

Cheers,
Andreas

Hi Andreas,

I don’t understand how a lower value could cause duplicate events from being handled.
When sourcing the aggregate from events, the first event can be a snapshot. In that case, the first event is generally the serialized aggregate itself. The events following that snapshot are events that had been applied after the snapshot was created. Those are applied again on the aggregate.

Are you sure some dates in your events aren’t reported twice, and therefore appear twice in the list of dates?

Cheers,

Allard