What you need is synchronous update, similar to the query, but with the ability to mutate the workflow state.
We have plans in adding such a feature, but in the meantime, there are a couple of workarounds to achieve what you want.
Signal then Query
The simplest approach is to signal workflow and then query it periodically until query will indicate that the request is successful or failed. Temporal guarantees read after write consistency of signal and then query pair.
The main drawback of this approach is that it introduces additional latency as query polling interval cannot be very low.
Use Local Activity to Notify
A little bit more complex approach is to use a local activity to unblock the caller.
Here is the sequence of steps to implement this:
- A process that initiates the request needs to expose an endpoint to complete the request.
- The synchronous request first sends a signal to the workflow. The signal arguments include a unique requestId as well as host and port of the client endpoint. Then it creates a channel (or
CompletableFuture
in case of JavaSDK) and inserts it into a map using requestId as a key. Then the requesting thread blocks on this channel receive (orFuture.get
). - Upon receiving the signal the workflow performs all the necessary activities and state transitions. Then to reply the workflow invokes the deliver result local activity. This activity invokes the complete request endpoint using the host and port and passing requestId as one of the arguments.
- As the host and port which are specific to the process are used the request handler is executed in the same process that sent the original signal. Then it gets from the map the channel (or
CompletableFuture
) that the original requested thread is blocked on and completes it with the result of the request received as another activity argument. - The original thread is unblocked by receiving the request result and can continue its execution.