Eventuous / eventuous

Event Sourcing library for .NET
https://eventuous.dev
Apache License 2.0
464 stars 73 forks source link

Additional metadata #81

Open alexeyzimarev opened 2 years ago

alexeyzimarev commented 2 years ago

Thinking about what to add to the default meta.

JulianMay commented 2 years ago

CorrelationId? CausationId?

I think it's fine to keep it tight for "defaults", should be easy for consumers to add specific stuff like:

alexeyzimarev commented 2 years ago

Correlation and causation id isn't easy as it would require commands to have an id. I am thinking about those too. Maybe the solution is to specify pre-defined header keys, and allow to pass a Metadata instance to the app service Handle.

Acting user id - yeah, we normally make it a part of the business (DoneBy property of each event), but maybe for impersonation scenarios, it would work differently.

Have you seen the Command API feature? The main issue with it is a missing context with all the important stuff, including the user identity. Again, it would work better if there would be a way to populate some of the properties from HttpContext, or have a convention to extract data from HttpContext and assign values to command properties.

Storing causation id would make little sense if commands aren't stored. You'd be having gaps in the sequence. It works fine with ESDB embedded projections and $correlationId as it gets populated for links and emitted events. But there, one event causes another event. On our side, it's a different flow, we have commands. Andrea Balducci talked about storing commands in Twitter, and I am thinking about the same for some time.

JulianMay commented 2 years ago

For CausationId i was only thinking about if the transition was caused by an event, having the commands as events would bridge this I agree.

I've been down the path of storing commands in eventstore, and found it useful for diagnostics but the first thing you'd want to archive (or simply discard) - we ended up only doing it for certain types of aggregates, writing "CommandHandled" events to a stream per aggregate ($"CommandsHandled-{streamId}"), and having those with a max age of 3 months (scavenging the rest).

I had not seen the Command API feature! Looks very neat :)

At my previous gig we would have an overload for dispatching command, which would take a "context enrichment", which was monoidic. The 'command dispatcher' could be wrapped so one instance was aware of being used in a http context (enriching metadata with userId etc.), while another would be used by process managers, being aware of which policy was being used etc.. I liked how this gave us a seam to isolate 'the metadata we always want for changes comming this way', while keeping the door open for additional case-specific metadata.

k3daevin commented 1 year ago

The actual date when the event was produced? This would be very helpful for auditing. If Clients would like to know the State at a given Timestamp, this is not possible with the current API. You can display the events and load the aggregate or the state up to a particular event (providing a custom Store.Load-Function with count as parameter), but not to a Timestamp. You could however achieve this by adding the Timestamp as a Domain property into each event. Although this feels like violating DDD principles.

(The created system meta of ESDB gets lost when migrating to another store) I was wondering why the Timestamp is not included in StreamEvent. Then the Timestamp might fit into Metadata.

A problem might be: what happens to old events when this new metadata is required? Set DateTime.Min or null?

If you have any plans on integrating the Creation Timestamp to the metadata, I'd love to contribute the Load-Functions for StateStore and AggregateStore with Timestamp as parameter.

alexeyzimarev commented 3 months ago

Creation date meta field could default to server-side creation date by default, it will be a special case.