Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Relational database schema for event sourcing

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:

  1. 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.
  2. 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?
  3. 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?
like image 436
inf3rno Avatar asked May 03 '14 00:05

inf3rno


1 Answers

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);
like image 182
Yugang Zhou Avatar answered Sep 19 '22 21:09

Yugang Zhou