Wait for signal from another service

Hey guys, im having some trouble to understand a scalable way to receive signals from other services in the orchestration.

Lets say i have those services:
- Customer Service
- Location Service
- Invoice Service
- Service Example (Orchestrator)
- Random Services…

So the flow inside Service Example is pretty much:

  1. create a new customer
  2. create a new location for that customer
  3. create an invoice
  4. wait for invoice approval (or rejection)
  5. notify user about the invoice status change

So i understood that it makes sense to keep those activities hosted by their respective services, so createCustomer() impl inside Customer Service, and so on…

But my Invoice Service would receive the commands to approve or reject the invoice based on a user input. How can i send this signal to the parent workflow running on Service Example?

I could pass the workflowId as a param to createInvoice(), and dispatch the signal from Invoice Service to Service Example workflow, but as you can see, i have a lot of other random services depending on createInvoice(), so they would need to implement the same method to receive this signal. And on top of that i have other services waiting for that invoice status change to start other flows (notifications, logs…)

In a event driven architecture i would just publish something like InvoiceStatusChanged, and all those services would listen for that and then execute their own flows.
In a temporal architecture this delegation responsability would be stuck with Invoice Service and it would need to know about all those services implementation details (so he can send the right signal, or call the right api endpoint for a callback…)

I dont know if it would help, but is there something like a global signal? Invoice Service would send this one signal (InvoiceStatusChanged) and other workflows could listen for that.

Or does it make sense for me to keep polling via rest Service ExampleInvoice Service so i can wait for a invoice status change?

I could use a message broker between them, and make the Service Example consumer listen for the event and dispatch the signal to the workflow. But i saw that it can be a little redundant to use temporal and a message broker at the same time.

Really would appreciate some help with that use case!

i have a lot of other random services depending on createInvoice(), so they would need to implement the same method to receive this signal

One possible solution is for InvoiceService to implement workflow that encapsulates both createInvoice activity and the user signal handling. This way all the calling services are going to wait on that workflow invoked as a child workflow without the need to handle the signal.

i have a lot of other random services depending on createInvoice(), so they would need to implement the same method to receive this signal.

I would let the InvoiceService workflow notify all these other services through signals or even invoke them as child workflows. It is not that complicated to maintain the list of the dependent services in one place. It would make troubleshooting much simpler.

I dont know if it would help, but is there something like a global signal? Invoice Service would send this one signal (InvoiceStatusChanged) and other workflows could listen for that.

We do realize that one-to-many notification is missing feature in Temporal and plan to address this limitation in the future.

Got it, thank you for the response!

I think for now ill use a thin layer of pub-sub between them, just for those one-to-many notification cases and to keep my services as uncoupled as i can, because im not really a fan of the invoice service team needing to know about those other services and making this “signal routing”.

Perhaps ill try to start all those parent workflows with a custom search attribute like a topic name. And them inside Invoice Service, query the running workflows “subscribed” to that topic name and send the signals.

1 Like