React to an event
Goal: when an event-sourced slice records something — a book is added, an author is registered — you want something else to happen automatically: a notification goes out, another system is told, a follow-up command runs. That’s a reactor.
This is part of Arc’s Chronicle integration. Direct database-backed Arc slices use commands, queries, and ordinary services; reactors become available when the write side records events in Chronicle.
A reactor does, a projection shows
Section titled “A reactor does, a projection shows”A projection builds queryable state; a reactor acts. Where you’d reach for a projection to display data, reach for a reactor to cause an effect. IReactor is a marker interface — there’s nothing to override. Arc dispatches to a method by the type of its first parameter, so adding an event type is all it takes to subscribe.
-
For a side effect, call a collaborator. Inject whatever does the work and handle the event:
public class NewArrivalsAnnouncer(INewArrivalsFeed feed) : IReactor{public async Task BookAdded(BookAddedToCatalog @event, EventContext context) =>await feed.Announce($"New on the shelf: {@event.Title}");} -
To change state, execute a command. A reactor must never touch the event log directly. When a reaction needs to produce new events, inject
ICommandPipelineand run a command — it goes through validation andHandle()like any other:public class CatalogIndexer(ICommandPipeline commands) : IReactor{public Task BookAdded(BookAddedToCatalog @event, EventContext context) =>commands.Execute(new IndexBookForSearch(@event.BookId, @event.Title));}
This is how one slice triggers another without either knowing the other’s internals — they meet only at the event.
See also
Section titled “See also”- Reactors — the full reactor model, dispatch, and failure behavior.
- Add event sourcing to an Arc slice — where reactors enter the Arc model.
- Return a result or an error — what the command you execute can return.