Some confusion about CQRS in Saving/Post callback


Hello, thank you very much for your tutorial about using CQRS with micro services! I am a big fan of your tutorial and after digging more into it, I become confused with a few concept around CQRS, could you please give me any hint or suggestion on those?

  1. Usage of your Command and Event message type in the project. It looks like both of them are very similar, no return object(immutable), both can be published and subscribe through RabbitMQ, I noticed that command was sent through dispatcher or RabbitMQ while event was only sent through RabbitMQ, but I mean seems like Command could replace the Event…, so what’s the core difference between those two and when should we use one over another?
  2. This is something I’m very interested, I assume that when perform WRITE operation we should use Command or Event, while when perform READ operation, we should use Query. However, sometimes, after we perform a WRITE operation, let’s say for example:
    • CreateDiscount from web application, with the usage of event DiscountCreated in your case as a callback and handled in EventHandler, yes we can sent email in event handler but we cannot return any information back to Client side like a message Your Discount Created Successfully or Something went wrong after retrying failed, our api gateway will always return nothing but a Accept() signal, so how could we or the client side know that my last WRITE operation performed successfully or not? I’ve seen you’re using the Operation Service and SignalR to catch the real-time response, very nice! But would it be redundant that SignalR had to subscribe message from Operation? I feel the Operation works like a middleware to transit the success or error response from internal API command handler, could we get rid of the Operation Service and let Discount Service talk directly to SignalR?
  3. The only handler that can return some data is Query Handler which I’ve seen you used it as performing READ operation, and it is unable to publish or subscribe through rabbitMQ, I guess it’s because for READ operation we need immediate action, correct? But why we need to do things like first dispatch then resolve by handler within same internal service, why not just do everything on API Controller level? I guess it may because of CQRS related principle, but not sure if that’s the correct way for doing every READ operation in this way or in what scenario we need to do like local dispatch for READ…would there be any latency by doing that?

Thank you again for your generous help and knowledge share! I really appreciate everything a lot!