Async Response Handling in a Workflow

Hi all,

We have a use case like the following.

Let’s say we have 4 activities in a workflow.
A B C D

As part of B, we need to submit a request to another web service that returns response asynchronously. (likely thru event)

The rest activities are synchronous. We want to proceed to C, and D without waiting for an asynchronous response from B. However, we want to mark the workflow as complete only when we get the asynchronous response back from B.

Is this something supported by Temporal? How would we go about doing something like this?

Which Temporal SDK are you using?

Would model B to just invoke your service (so would have short StartToClose timeout), then invoke activities C, D, then await response from B via for example workflow.Await (Go SDK) before completing your workflow. If response signal comes while your workflow is executing C, D, workflow.Await condition would unblock immediately.

@tihomir Thank you for your response.
We are using Java SDK. One thing I’m concerned about with the approach you suggested is that we may be blocking too many threads if there is a large number of concurrent executions that are running.

Just thinking out loud here but, is it possible to return activity B without waiting for the result, then continue to operate on activity C and D, and somehow notify activity B once the asynchronous event comes back?

(I think it’s similar to what’s being described in Developer's guide - Features | Temporal Documentation but not 100% sure)

You can have many more workflow executions than threads available in the worker. So you shouldn’t really be concerned about this.

@maxim If we do workflow.Await per the suggestion, wouldn’t we be blocking the thread? (so 1 workflow holding up 1 thread essentially?)

It will block the workflow thread. But workflow that is blocked doesn’t consume a thread on the worker. Currently, it is not even possible to implement a Java workflow that doesn’t block at least one thread as a workflow is closed the moment its main method returns.

The implementation is more complex as cached workflows consume threads, but this is a pure performance optimization as they can be kicked out of the cache at any time.

@maxim Thanks for your response! What you said makes sense.

I have 2 follow up questions -

1. What will happen if all threads in the workflow thread pool are “awaiting”?

Based on Question about Workflow.await and Workflow.sleep , I gathered Temporal is performing some optimization under the hood to release threads that are doing “workflow.await” if it needs to do work on another workflow.

Just wanted to make sure we don’t run into a situation where all threads in a pool are blocked and prevent new workflow from starting.

Is my understanding of how workflow threads work w.r.t “await” correct?

2. What would this look like when we get an asynchronous response thru event such as Kafka or SQS?

For example,
A → B (submit async reqeust to another service) → C → D → B’ (receives B completion event thru Kafka or SQS)

Not sure how B’ will exactly work with “workflow.await” in this case. Could you please shed some light on how this could work?

1. What will happen if all threads in the workflow thread pool are “awaiting”?

A new workflow task will either unblock one of the waiting workflows or if this task is for a workflow not currently cached then one of the cached workflows will be kicked out of the cache and the threads it consumed will be released back to the pool. So a newly loaded workflow can continue executing.

2. What would this look like when we get an asynchronous response thru event such as Kafka or SQS?

In Java SDK a signal handler will update a variable the workflow is waiting on. And then after the await is unblocked the workflow is going to continue executing the main thread.

@tihomir @maxim Thank you so much!