0

I'm working on architecting a micro-service solution where most code will be C# and most likely Angular for any front end. My question is about message chaining. I am still figuring out what message broker to use; Azure Service Bus , RabbitMQ, etc.. There is a concept which I haven't found much about.

How do I handle cases when I want to fire a message when a specific set of messages have fired. An example but not part of my actual solution: I want to say Notify someone when pays a bill. We send a message "PAIDBILL" which will fire off microservices which will be processed independently:

  1. FinanceService to Debit the ledger and fire "PaymentPosted"

  2. EmailService: email Customer Saying thank you for paying the bill "CustomerPaymentEmailSent"

  3. DiscountService: Check if they get a discount for paying on time then send "CustomerCanGetPaymentDiscount"

If all three messages have fired for the Same PAIDBILL: Message "PaymentPosted", "CustomerPaymentEmailSent", "CustomerCanGetPaymentDiscount" then I want to email the customer that they will get a discount on their next bill. It Must be done AFTER all three have tiggered and the order doesn't matter. How do I Schedule a new message to be sent "EmailNextTimeDiscount" message, without having to poll for what messages have fired every minute, hour, day?

All I can think of is to have a SQL table which marks that each one is complete (by locking the table) and when the last one is filled then send off the message. Would this be a good solution? I find it an anti-pattern for the micro-service & message queue design.

David Buck
  • 3,752
  • 35
  • 31
  • 35
greektreat
  • 2,329
  • 3
  • 30
  • 53

1 Answers1

1

If you're using messages (e.g. Service Bus / RabbitMQ), then I think the solution you have described is the best one. This type of design - where services have knowledge about the other domains in the system - is typically known as choreography.

You'll want to pick a service which will be responsible for this business logic. That service will need to receive all the preceding types of messages so that it can determine when (if) all have been met, which it probably wants to do by recording which of the gates have already passed in a database.

One alternative you could consider is chaining the business processes instead of doing them in parallel. So...

  1. PAYBILL causes FinanceService to Debit the ledger and fire "PaymentPosted"
  2. "PayentPosted" causes EmailService to email Customer Saying thank you for paying the bill and broadcasts "CustomerPaymentEmailSent"
  3. "CustomerPaymentEmailSent" causes DicsountService to check if they get a discount for paying on Time then sends "CustomerCanGetPaymentDiscount"
  4. The email you want to send is just triggered by "CustomerCanGetPaymentDiscount".

If I'm honest, I would switch around the dependency model you're using at this last stage. So, instead of some component listening for "CustomerCanGetPaymentDiscount" events from DiscountService and sending an email, I think I would instead have the DiscountService tell some other component to send an email. It seems natural to me for something that calculates discounts to know that an email should be sent. It seems less natural for something that sends emails to know about discounts (and everything else that needs emails sent). This is why I don't like architectures where the assumption is that every message should be an event and every action should be triggered by an event: it removes a lot of decisions about where domain logic can live, because the message receiver always has to know about the domain of the message sender, never vice versa.

Graham Lea
  • 5,797
  • 3
  • 40
  • 55
  • This example isn't what I am specifically handling , this was theoretical as part of my design I need to have a solution for any situation which could be based like this. Thank you for the definition I didn't know it was called choreography which does make sense. Is there a different architecture that can handle choreography than messages? – greektreat Nov 15 '19 at 14:57
  • You could, in theory, do the choreography using synchronous messaging, but that would be atypical, especially bc synchronous comms are more commonly used for commands, where A tells B to do something, than events, where B is listening for A to advice completion of something. (Webhooks are an obvious exception to this, due to their inversion of control.) And, in general, once an architecture starts getting relatively large I advise to prefer asynchronous comms wherever possible, to limit temporal coupling. – Graham Lea Nov 16 '19 at 10:10
  • If you're looking to avoid messaging in favour of synchronous comms, you may want to look into the alternative to choreography, which is orchestration. Think of choreography as being a set of semi-loosely-coupled services interacting with each other to achieve a goal larger than any of them are aware of. Orchestration is instead where the individual services are more loosely coupled to each other, but there is a centralised service which is driving the steps of the workflow. That service understands and strives to achieve the whole larger goal. – Graham Lea Nov 16 '19 at 10:14