Domain events and commands
Events and Commands registered in the default template's Reaction system and how they are processed.
A business change first produces an Event, which then creates one or more Commands. Reaction only processes definitions registered in src/core/reaction/events/index.ts and src/core/reaction/commands/index.ts.
Event
EventInput
Prop
Type
Registered Events
| Event | type | Key inputs | Commands created |
|---|---|---|---|
UserSignupEvent | user_signed_up | Subject, source, and optional roles and signup email | grant_role, send_email |
UserEmailVerifiedEvent | user_email_verified | User subject, verifiedEmail, emailHash, verifiedAt, and purpose | Creates grant_role when account email verification succeeds and the email matches the administrator list |
PaymentSucceededEvent | payment_succeeded | Subject, source, and optional roles and entitlements | grant_role, grant_entitlement |
SubscriptionCreatedEvent | subscription_created | Subject, subscription source, and optional roles and entitlements | grant_role, grant_entitlement |
SubscriptionUpdatedEvent | subscription_updated | Subject, subscription source, and optional complete role and entitlement configurations | Revokes existing grants from this source, then grants them again using the new configuration |
SubscriptionEndedEvent | subscription_ended | Subject, subscription source, and optional roles and entitlements | revoke_role, revoke_entitlement |
UserEmailUpdatedEvent | user_email_updated | User subject, email hash, and optional notification data for the old email address | Synchronizes the email address with payment providers and sends a security alert to the old address as needed |
UserTwoFactorSecurityChangedEvent | user_two_factor_security_changed | User, email, name, language, occurrence time, and security settings URL | send_email |
EntitlementCycleDueEvent | entitlement_cycle_due | Optional next recurring entitlement record | process_due_entitlement_cycles |
DataCleanupEvent | data_cleanup | olderThan | purge_stale_data |
NotificationRequestedEvent | notification_requested | Notification destination and message | send_notification |
When SubscriptionUpdatedEvent and SubscriptionEndedEvent process roles and entitlements, an absent field differs from an empty array. An absent field leaves that category of data untouched. An empty array revokes all roles or entitlements from that source.
The purpose of UserEmailVerifiedEvent is either account or password_reset. Only the site's account email verification flow grants the admin role based on an exact match in adminEmails. Password reset verification does not grant this role, and an OAuth provider's claim that an email is verified cannot replace verification on this site.
UserEmailUpdatedEvent defaults to continueOnFailure: true. Synchronizing the payment email and sending the security alert are independent. Even if one still fails after retries, the other continues to execute.
Command
CommandDraft
Prop
Type
key only distinguishes steps within the same Event. It does not determine execution order or serve as the Event's idempotency key or the Command execution ID.
Registered Commands
| Command | type | Mode | Purpose |
|---|---|---|---|
GrantRoleCommand | grant_role | sync | Grant roles to a subject by source |
RevokeRoleCommand | revoke_role | sync | Revoke roles or static capabilities by source |
GrantEntitlementCommand | grant_entitlement | sync | Grant entitlements to a subject by source |
RevokeEntitlementCommand | revoke_entitlement | sync | Revoke entitlements or dynamic capabilities by source |
SendEmailCommand | send_email | async | Render a registered email template and send the email |
SendNotificationCommand | send_notification | async | Send a message through the configured notification channels |
CreateUserNotificationCommand | create_user_notification | async | Create a published in-app notification, using the Command ID as the notification ID |
SyncPaymentCustomerEmailCommand | sync_payment_customer_email | async | Synchronize the user's latest verified email address with the payment provider's Customer |
ProcessDueEntitlementCyclesCommand | process_due_entitlement_cycles | async | Process recurring entitlements that are due and schedule the next execution |
PurgeStaleDataCommand | purge_stale_data | async | Delete data older than the specified time |
All Commands in the template default to version 1 and a maximum of 3 attempts. Each Command definition can set these values independently. When an Event creates a Command, it can also override maxAttempts for that execution alone.
sync Commands are processed immediately during Event execution. async Commands are sent to ASYNC_POLICY_TASK_QUEUE. Both modes write execution records to command_execution.
Execution statuses
EventExecutionStatus
| Value | Meaning |
|---|---|
processing | No termination condition has been met, and Commands are still waiting to execute |
completed | No Commands are pending or in a business failure or exception state |
partial_failed | continueOnFailure is true, all Commands have finished, and at least one returned a business failure |
failed | continueOnFailure is false, and at least one Command returned a business failure |
errored | At least one Command threw an exception during execution |
An Event's status is calculated from its Command statuses rather than stored separately, avoiding inconsistencies between two copies of the status.
CommandExecutionStatus
pending, succeeded, failed, and errored mean waiting to execute, successful execution, a returned business failure, and a thrown exception, respectively.
Registration locations
Add each new Event to the events array in src/core/reaction/events/index.ts and each new Command to the commands array in src/core/reaction/commands/index.ts. Reaction will not recognize a definition if you only create its file without registering it.