Declarative constraints
The declarative API lets you define constraints in a dedicated class by implementing IConstraint. Chronicle discovers all IConstraint implementations automatically — no registration is needed.
Use declarative constraints when you need:
- Uniqueness spanning multiple event types with different property names
- A callback to compose dynamic violation messages
- More explicit control over constraint names
Constraint types
Section titled “Constraint types”| Type | Description |
|---|---|
| Unique property | Enforce that a property value is unique across one or more event types |
| Unique event type | Enforce that only one event of a specific type can be appended per event source |
| Closing stream | Close a stream scope when an event of a specific type is appended |
Defining a constraint
Section titled “Defining a constraint”Implement IConstraint and call the builder in Define:
using Cratis.Chronicle.Events;using Cratis.Chronicle.Events.Constraints;
[EventType]public record ConstraintsDeclarativeIndexProjectCreated(string Name);
[EventType]public record ConstraintsDeclarativeIndexProjectRemoved;
public class ConstraintsDeclarativeIndexUniqueProjectName : IConstraint{ public void Define(IConstraintBuilder builder) => builder.Unique(unique => unique .On<ConstraintsDeclarativeIndexProjectCreated>(e => e.Name) .RemovedWith<ConstraintsDeclarativeIndexProjectRemoved>());}Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.ConstraintsDeclarativeIndexProjectCreated do use Chronicle.Events.EventType, id: "constraints-declarative-index-project-created" defstruct name: ""end
defmodule MyApp.Events.ConstraintsDeclarativeIndexProjectRemoved do use Chronicle.Events.EventType, id: "constraints-declarative-index-project-removed" defstruct []end
defmodule MyApp.Constraints.ConstraintsDeclarativeIndexUniqueProjectName do use Chronicle.Events.Constraint
unique name: "ConstraintsDeclarativeIndexUniqueProjectName" do on MyApp.Events.ConstraintsDeclarativeIndexProjectCreated, [:name] removed_with MyApp.Events.ConstraintsDeclarativeIndexProjectRemoved endendimport { constraint, eventType, IConstraint, IConstraintBuilder } from '@cratis/chronicle';import { field } from '@cratis/fundamentals';
@eventType()class ConstraintsDeclarativeIndexProjectCreated { @field(String) readonly name: string;
constructor(name: string) { this.name = name; }}
@eventType()class ConstraintsDeclarativeIndexProjectRemoved {}
@constraint()class ConstraintsDeclarativeIndexUniqueProjectName implements IConstraint { define(builder: IConstraintBuilder): void { builder.unique(unique => unique .on(ConstraintsDeclarativeIndexProjectCreated, e => e.name) .removedWith(ConstraintsDeclarativeIndexProjectRemoved)); }}Discovery
Section titled “Discovery”Chronicle scans all loaded assemblies for types that implement IConstraint and registers them with the Kernel automatically when the client starts. No explicit registration is required.