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.