Table of Contents

Unique event type constraint

Adorn the event type class with [Unique] to enforce that only one event of this type can be appended per event source. Use this when the event itself is a unique fact — for example, registering a user can only happen once.

Chronicle discovers [Unique]-adorned types automatically and registers the constraints with the Kernel when the client starts.

Defining a unique event type constraint

[EventType]
[Unique]
public record UserRegistered(string Email, string DisplayName);

Constraint name and violation message

An optional constraint name and violation message can be provided:

[EventType]
[Unique(name: "UniqueUser", message: "A user with this identity has already been registered.")]
public record UserRegistered(string Email, string DisplayName);

The message parameter is optional. Chronicle produces a default violation message when one is not supplied.

Releasing a constraint

Apply [RemoveConstraint] to the event type that signals a domain object has been removed. When this event is appended, Chronicle releases the constraint, and the event source can accept a new event of this type:

[EventType]
[RemoveConstraint("UniqueUser")]
public record UserRemoved(UserId UserId);

The constraint name must exactly match the name provided to the [Unique] attribute. When no name was provided to [Unique], Chronicle uses the event type name as the default constraint name.

How constraints are enforced

The Chronicle Kernel reads the [Unique] and [RemoveConstraint] attributes when the client connects and creates the indexes it needs. Every subsequent append is checked against those indexes server-side, so no constraint logic runs in client code.