Skip to content

Consistency enforcement

Duncan Jones edited this page Sep 11, 2020 · 3 revisions

When writing to an event stream there are three consistency enforcement options that can be set which will prevent an event being written if they are not met.

The entity must not already exist

To require this constraint, set the stream constraint parameter on the AppendEvent call to EventStreamExistenceConstraint.MustBeNew.

This type of constraint is useful where an entity identifier must be unique and the command is attempting to create a new entity.

                try
                {
                    await bankAccountEvents.AppendEvent(evtOpened,
                        streamConstraint: EventStreamExistenceConstraint.MustBeNew
                        );
                }
                catch (EventStreamWriteException exWrite)
                {
                    return req.CreateResponse<FunctionResponse>(System.Net.HttpStatusCode.Conflict,
                        FunctionResponse.CreateResponse(startTime,
                        true,
                        $"Account {accountnumber} had a conflict error on creation {exWrite.Message }"),
                        FunctionResponse.MEDIA_TYPE);
                }

The entity must already exist

This is the opposite of the above and is useful if the command should not be the first thing to happen to an entity - this is done by setting the stream constraint parameter on the AppendEvent call to EventStreamExistenceConstraint.MustExist.

No new events have occurred since the given position

There are some cases where you may have run a projection to get state data that you are then reliant on to decide if the command can go ahead or not. You would therefore want the write to fail if any other events have been appended to the [event stream] since you got that projection. This is done by passing in the expected last event number in the expectedTopSequence parameter:

                        try
                        {
                            await bankAccountEvents.AppendEvent(evWithdrawn, projectedBalance.CurrentSequenceNumber);
                        }
                        catch (EventSourcingOnAzureFunctions.Common.EventSourcing.Exceptions.EventStreamWriteException exWrite  )
                        {
                            return req.CreateResponse<ProjectionFunctionResponse>(System.Net.HttpStatusCode.Forbidden,
                                    ProjectionFunctionResponse.CreateResponse(startTime,
                                    true,
                                    $"Failed to write withdrawal event {exWrite.Message}",
                                    0),
                                    FunctionResponse.MEDIA_TYPE);

                        }

If an attempt is made to write an event which violates these then an EventStreamWriteException is thrown which can be trapped and the decision to retry or discard the command that was writing the event can be made.