Open arianvp opened 7 years ago
I went down this path a few months ago and decided not to modify the definition of Aggregate
. The reason is because there are way too many subtle variations with how users of this library would want to handle errors, and committing to one way as the "blessed" way seems folly.
In my opinion there are a few options here:
event :: Either EmailError EmailEvent
. Then in your code that actually uses the Aggregate
, you can do whatever you want when you encounter any Left EmailError
values. If you encounter these you can either not write these events to the event store, or not write any events.state -> [EmailError]
(this could even be a field if your state is a record type) that you can use to decide to fail your command handler. More specifically, if someone gives you an invalid event, then when you project it onto your state you can flip some bit that says it is invalid. Then you can read your state and the command handler function can use that information how it wishes.eventful
Aggregate
and indeed use your own! Yours is a perfectly fine abstraction. The real question of "what happens when a command is invalid" is handled in your handler code anyway, so whatever mechanism you use to determine a command is invalid is mainly a question of ergonomics.The goal of eventful
is to be a toolbox, not a framework, so my hope is to make the tools general enough to be used a la carte and not be too interdependent.
Also by the way, in the latest version of eventful
Aggregate
was renamed to CommandHandler
. I didn't realize I haven't made a release in a few months, I should get on that...
As an aside, after talking with a few users I'm thinking of moving some of the opinionated abstractions like CommandHandler
, ProcessManager
, ProjectionCache
, etc either to the docs or to some library that indicates they aren't the only way to do things (maybe call it eventful-simple
?). Other eventful
libraries would then deal principally with handling events, event storage, reading events, that type of thing.
I don't want users to think these are the only ways of doing things, or that they are even the most general ways of doing things. In your case, I would much rather you use the command handling abstraction that you like using best instead of having to do either of the suggestions I mentioned above.
The current definition of
Aggregate
is as follows:But people tell me I should never trust user input. What if the incoming command is invalid? How would I handle this? Usually I have something like:
Would I have to map errors to "events" ? Such that, an invalid command inserts an
ErrorOccured <reason>
event?But that would give you superflous events that probably should not affect the state in the
Projection