Registering Event Schemas
Every event type has a JSON schema, derived from the struct or its own (see Describing Events with Schemas), but the database only checks events against a schema once it is registered. The enum of the events of a state collects the schemas of all its variants. To get them as a Vec of EventSchema, each with the functions event_type and schema, call the schemas function of the enum, as in BookEvent::schemas().
Then hand them over to the register_schemas function of the store:
store.register_schemas(BookEvent::schemas()).await?;
register_schemas takes any iterator of schemas, so it accepts the schemas of several states at once, chained together. An event type that several of them bring along with the same schema is registered once. If they bring it along with two different schemas, register_schemas fails with a permanent failure, as in permanent failure: event type "io.eventsourcingdb.library.book-borrowed" has two different schemas, before it registers anything. Call it on every start, before the application serves requests: for an event type the database knows already, it checks that the registered schema is exactly the one from the code. A registration that has begun runs on a task of its own, so that it is finished even if the future of register_schemas is dropped, but none begins once the future is gone.
An event that no state has a variant for, such as InventoryTaken, which only write writes (see Writing to Several Subjects), is part of no schemas. To register its schema as well, call EventSchema::of with the type of the event. It returns the event type and the schema of the event, its own or the derived one, which goes into the same iterator:
use architecturekit::EventSchema;
store
.register_schemas(BookEvent::schemas().into_iter().chain([EventSchema::of::<InventoryTaken>()]))
.await?;
Changing a Schema#
A registered schema can not change. If it differs from the one from the code, register_schemas fails with a permanent failure, as in permanent failure: the schema of "io.eventsourcingdb.library.book-borrowed" differs from the registered one, which cannot change; introduce a new event type and an upcaster instead, so that the application does not start with a schema the database does not enforce. It does the same if the database refuses a schema, for example because stored events of the type do not match it. The error names the event type, and its source, the error of the client SDK, holds the description the database gives.
To change the shape of an event, introduce a new event type instead, and translate the stored events of the old type with an upcaster (see Versioning Events).
Note that this also holds if you remove the schema_with function of an event whose schema is registered already: the derived schema has to be exactly the registered one, or register_schemas fails. Keep the function of such an event, unless you have compared both.
Writing Events That Do Not Match#
Once a schema is registered, the database rejects every event of the type that does not match it. execute then fails with ExecuteError::Permanent, because writing the same event again gives the same result, as in permanent failure: writing "/books/42". Its source, the error of the client SDK, holds the description the database gives, for example from EventSourcingDB 1.3:
The DB returned the error https://docs.eventsourcingdb.io/errors/event-schema-violated with status 200 OK: /events/0: event does not match the schema of its type: additionalProperties 'tags' not allowed