I am trying to store domain events in a postgres database. I am not sure in many things, and I don't want to redesign this structure later, so I am seeking for guidance from people who have experience with event sourcing. I have currently the following table:
domain events
version - or event id, integer sequence, helps to maintain order by replays
type - event type, probably classname with namespace
aggregate - aggregate id, probably random string for each aggregate
timestamp - when the event occured
promoter - the promoter of the event, probably user id
details - json encoded data about the properties
What I am not sure:
- Should I store the promoter of the domain event?
It could help to find a compromised account by security breaches, but I don't know what to store for example by a CRONjob. - In what format should I store the event type?
Should I add a table with event types, or are the class names enough?
Should I add event groups? - I got confused by the definition of bounded contexts. As far as I know, every aggregate can have multiple bounded contexts, so I can use different aspects of a single aggregate in multiple modules. That sounds nice, since for example accounts can be related to many things, including authentication, authorization, user profile, user posts, user contracts, and so on...
What I am unsure, that a domain event can have multiple bounded contexts, or just a single one, so should I store event contexts as well? (for cases I want to replay events related to a single context)
How to implements so many properties in a single aggregate class, should I use some kind of composition?
1.Should I store the promoter of the domain event?
I think it's more flex if you store the promoter as part of the event payload instead of meta data. The security concerns should be handled outside the domain. Not every event is raised by a user, although you could make a fake one for them(a SysAdmin for CronJob).
For example:
ManualPaymentMadeEvent { //store this object as details in your schema
amount,
by_user//In this case, developers can determine whether store the promoter case by case
}
2.what format should I store the event type?
Should I add a table with event types, or are the class names enough? Should I add event groups?
I think class names is enough. Adding another table complicates event read(by join tables), and I think it only adds value when the class names is renamed(Update one row in event type table). But I think it does not add much trouble by using
update domain_events set
aggregate_type = 'new class name'
where aggregate_type = 'origin class name'
I'm not sure that I understand event groups, could you add more explanation?
3.What I am unsure, that a domain event can have multiple bounded contexts, or just a single one, so should I store event contexts as well?
Sometimes the events are used to integrate multiple contexts. But each event is raised only in one context. For example, A ManualPaymentMadeEvent is raised in ordering context, and an event listner in shipping context also consumes it, regards it as the trigger of start shipping.
I prefer to use per database user(oracle term) per context. shipping.domain_events for shipping context and ordering.domain_events for ordering context.
Here is the schema in axon-framework which might help
create table DomainEventEntry (
aggregateIdentifier varchar2(255) not null,
sequenceNumber number(19,0) not null,
type varchar2(255) not null, --aggregate class name
eventIdentifier varchar2(255) not null,
metaData blob,
payload blob not null, -- details
payloadRevision varchar2(255),
payloadType varchar2(255) not null, --event class name
timeStamp varchar2(255) not null
);
alter table DomainEventEntry
add constraint PK_DomainEventEntry primary key (aggregateIdentifier, sequenceNumber, type);
来源:https://stackoverflow.com/questions/23438963/relational-database-schema-for-event-sourcing