5

Suppose you have a bounded context with ~30 business events and, for simplicity sake, the same number of commands like ChangeUserEmailCommand -> UserEmailChangedEvent initiated from a web UI. Processing a command may fail for the following main reasons (besides infrastructure failures of course):

  1. Validation issue (email uniqueness)
  2. Technical issue (optimistic concurrency version mismatch)

I'd be interested to provide the best user experience to the clients and display what went wrong.

What is the best practice to signal the failures?

  1. Would you create 30 more events like ChangeUserEmailFailedEvent? If not, what's your rule of thumb for which events to create a paired *FailedEvent?
  2. Is it a good idea to just have bool Success {get;set;} property in the existing events? It's probably not the best way when you need to signal more failure details than just an error message
  3. Would you create a single ConcurrencyFailedEvent for all concurrency issues adding a source command type as part of it's payload? Just to separate this kind of failure from business validation failures?

The commands are processed asynchronously (via a broker). The read storage is separated from the write storage. No event sourcing.

As for why would I need this I can think of the following:

  1. Detailed error message pushed back to a client via web sockets, for example
  2. Threat detection - reacting to an increased number of failed user registration which might be an attack
  3. Monitoring - displaying a number of failed orders on a dashboard, for example. If it's within a certain range I'd feel safe letting the support handle it. If it's above a certain number - I probably need to dig the logs.
9
  • 1
    As usual: It depends. What are your requirements? Please add more details to your question. – helb Feb 24 '20 at 11:43
  • Thanks, updated as much as I could. Imo, these requirements are rarely part of what engineering teams get as an input. I hope to hear some practical advice from whoever built real life systems with EDA because there is not much information on the subject in those dozens of videos/article I've read so far. – UserControl Feb 24 '20 at 12:06
  • 1
    There are also non-formal requirements to consider. It seems that you want to notify event listeners when an action failed (wich would normally lead to an event). Why do you want to achieve this? Is it important? What should event listeners do when they are notified about a failed action? – helb Feb 24 '20 at 12:51
  • How are your commands processed? Synchronously or asynchronously? Do you have eventual consistency implemented? – Andy Feb 24 '20 at 12:58
  • @Andy, Thanks for clarifying! Added extra details. – UserControl Feb 24 '20 at 13:08
2

Seems to me like you can get away with a single type

ErrorEvent
    EventId
    ErredEventId
    ErrorType
    Message

If you just have generic errors to deal with, but I would go further and remove Error events for UI stuff.

If the user is waiting to see if something erred you can pass the error back from the function they called and only write the event on success.

So, just EmailUpdated instead of EmailUpdateRequest EmailUpdateFailed EmailUpdated etc etc

You can see how going fully event driven can explode the number of types you need. If they are all internal to a thick client, then you have compile time checking to handle it all, but if you have to pass them over a distributed system it becomes ridiculous

2
  • I think it boils down to: Can the user recover from the error? If no, all they need is a message saying "an error occurred". They can't do anything anyway, so alert and tell them to try again later. If they can recover then you need the message and other data to determine what to do next as indicated here. – Jon Raynor Feb 24 '20 at 19:40
  • Id say its more, can the system self recover. If there is a human they can read the mesage. If its a computer they need structured data – Ewan Feb 24 '20 at 21:18
1
  1. From your question I've understood ChangeUserEmailFailedEvent is a core part of your domain. So it should be always stored. The thing is that you can't predict how your business requirements will change so it's better to store your domain events just in case.
  2. Not sure what bool Processing {get;set;} means. In case it's not a domain concept - better omit it.
  3. Technical issues should not be stored in event logs as there are no business values in them. For tech-related stuff, you should maintain separate application log. (I mean like plain text files or Elastic APM logs or Logstash. I hope you get my point).
2
  • Thanks. What do you mean by "it should be always stored"? I'm not using Event Sourcing. As for #2 - it was a typo, my bad (should be Success, renamed the property). – UserControl Feb 24 '20 at 17:39
  • 1
    "I'm not using Event Sourcing" - my bad, missed that. Still, I'd stick to firing all those events that are used by business domain. Regarding Success property, I think it's better to pass some sort of EventArgs class with all info needed to handle the event correctly – Bohdan Stupak Feb 25 '20 at 10:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.