-
-
Notifications
You must be signed in to change notification settings - Fork 455
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Event Metadata #780
Comments
For me personally I would like to use event metadata for the following cases:
In both of these cases the only thing I would really require is an api similar to Im always a bit wary of introducing Im thinking maybe something like
At this point maybe we could wrap the AccountOpenedMetadata in a wrapper class that adds a link back to the original event, and store the metadata as a normal marten document (which could make attributes such as Not at all sure if this is a good idea, or how doable it would be but I figured Id throw the idea out there and see what you think. |
@wastaz perhaps I'm misunderstanding but it sounds like everything you described is already doable in Marten. If you want to store changes to events as well as a "metadata" document, you can do that in one Am I understanding you or am I missing something? |
@jeffdoolittle Well, yes and no. It's certainly possible today, but there's a bit of heavy lifting involved and it's not really possible to get it done in "one query" without writing direct sql queries against the tables. Basically my point is that if we are considering event metadata as a feature and we already have the docstore stuff in marten then why not try to use it as much as possible? :) |
I don't recall off the top of my head, but can you do a batch query that includes documents and events? Might help if your concern is trips to the database. To be clear, I'm not opposed to Event Metadata, just trying to understand how people would want to use it so we can come up with a good abstraction and api for it that will stand the test of time. |
I'm evaluating Marten and stumbled on this issue almost instantly. Metadata is important part Some of metadata fields I usually use are: user Id and scopes, correlation/causation ids (especially useful when debugging process managers). Your aggregate might have zero knowledge of these but they should be written along side business data - event. Seems like it can be achieved by using data envelope like:
But it feels like it'll make code especially aggregates uglier. |
Also evaluating Marten and lack of metadata capability is a big deal. Other frameworks provide this readily, and an enterprise event store needs to be able to handle metadata/headers. @aprooks , I actually pursued that route and there's some deserialization bug lurking within Marten that actually renders that route infeasible for now. See #1069 for details. |
@eouw0o83hf This got left out of Marten 2.0 because it's a lot of work and there wasn't much demand for it at the time. Since it is an awful lot of work to support this and there's very little concrete definition about what it means or how it'd be used, can you add some concrete examples of what you want here? And as I commented in #1069, you could easily effect this yourself with a base class |
@jeremydmiller definitely doable with a base class (and absolutely understand that "not enough of a priority" reasoning), but I've used NEventStore in the past and the ability to persist headers gave a lot of extra strength to an event-sourcing framework when called upon as an audit log (for either security/"who did this" purposes or debugging/"what did the user do" purposes). Top few things I've tossed into headers/metadata that were super useful:
|
Oh and also in direct response to the original question, I think a straightforward |
I would recommend a byte[] outside of event , like Event store does .. There are many cases where you want to read all the events get the metadata but not de-serialize all the bodies. |
@bklooste YOu can do that to your heart's content with SQL as is |
@jeremydmiller Note the use case of category or aggregate streams which may be > 100M events and you don't want to deserialize them all . |
What is the actual difference between "data" and "metadata" in this case? If by metadata meant something specific to a particular event type, why not put in "data" (payload)? Where is the actual boundary between data metadata? How should one determine what specifics deserves to go to metadata vs event data? |
metadata is application/protocol specific. Imagine HTTP-headers: you might have a required attribute (Authorize) and some helpers, like x-tracing-id. So anything very general, applicable to all event types, and modifiable during handling pipelines could be stored alongside a message body and be called metadata. The approach you described will work, but it will be semantically wrong. |
@whitecolor the key thing is it requires the consumer to inspect and know the data structure. Metadata tends to be a universal / loose structure which can also be used to make decisions on where data should be routed or partitioned without knowing the data structure. It should also be small where as a data message maybe a Meg. |
Note here several types of metadata an organization may employ and note while a message is typically immutable , metadata may not be. Its important to be able to guarantee bodies are immutable. Here are the 3 key scenarios in decreasing order of importance. I tend to use some of 1 and 2.
|
Ok, thanks for elaboration, let's see the example case: |
UserId could be stored as part of the metadata for every event. For example, if there is a requirement to have a fully traceable to a User audit log of every change in a system. The same UserId could be part of business logic and event body, for example, if you have a requirement like "a user can only toggle an item created by himself". There is nothing bad if data occasionally duplicates. Those fields will be handled separately by different application layers/parts/components. |
I was also thinking about adding Metadata, for sure I'd see there something like I don't have specific design yet, but the first guess would be to add it as new column simmilar to |
This is what we are using Time and NodeId are time event was created and node where it was created which can be different to the time its inserted in the DB especially if you have multiple DBs
} CorrelationId and CausationId come from Event store - note the pattern here its a json document but the db uses JObject["$correlationId"] so the consumer is free to use any structure they choose. |
@oskardudycz I created a POC implementation of metadata column no so long ago - https://github.com/JasperFx/marten/compare/master...jacobpovar:metadataColumn?expand=1. Not completely finished, but might be worth to take a look at. |
@jacobpovar @oskardudycz Just a couple thoughts on the POC code:
|
Other options around serialization. Could also leave it at byte[] and leave it up to the consumer , some people may just put a guid in there. Note a huge / key difference is metadata is normally the same fixed type for all events vs different types for the event. This allows more optimal custom serialization / deserialization. 2 optional Factory Funcs could help people here. Agree should be opt in . Id forget about any mights / shoulds - get the basics in do it well , enhance later. Focus on persistence structure /schema. |
@bklooste Thanks for the input. The "mights" and "shoulds" above are questions about how to pull it off, and not necessarily about features. The custom factory Funcs are interesting, but i'm not sure about the usability. I'm also trying to think about how the metadata is going to be consumed from both straight up SQL querying and C# code. Making it a byte[] renders the data almost useful w/o the C# code and that's something else to consider. |
Basically AddMetaData ( Func<T, byte[]) metadataCreator = null , Func<T, byte[]) metadataWriter = null ) params on setup where T is the metadata type .. AddMetaData ( val => val.ToByteArray() ,val => new Guid( val)); or add custom json serializer, convert to new metadata type or anything else. |
There is a PR for adding Metadata to documents from @barryhagan. Interested persons are welcome to pleas the comments there :) #1364 |
Tasks
|
Had a couple folks ask lately if there was any way to embed metadata into the event store. The usual examples are things like customer id or region names.
We could handle this by saying "just use base classes for the common information." From there we'd possibly allow some aggregated querying against the event store by the base type.
Other ideas:
The question though becomes how do we expose that information and allow users to search on it? Sticking a
Dictionary<string, object>
property onEvent
is no big deal.I guess my question is, what would you use this for? Where would you want to consume this information?
Also really unsure how we'd go about capturing this information in the
IEventStore
APIThe text was updated successfully, but these errors were encountered: