Asynchronously waiting on multiple signals and conditions in the Workflow

Hi team, I have been using Temporal Workflows for a while but in my attempt to expand the scope of their utility, I’m stuck upon a problem while using signals and Workflow.await command.

I currently have a workflow that generates a packet, wait for admins to sign the packet and uploads the signed packet. The key is that at least 3 admins should send their signed packets to proceed with the upload activity. To achieve this, I have:

  1. Activity 1: generatePacket()
  2. Signal to send admin-signed packet to the Workflow
  3. Activity 2: uploadSignedPackets()
        Map<String, Object> pkt = myWorkflow.downloadPacket(nodeId);

         //wait for admins to sign packet and signal them to the workflow
         Workflow.await(() -> pkt.quorum <= 0);
  
         //upload all the signed packets received
         myWorkflow.uploadSignedPackets(pkt.signedPktsList);

This is how my signal method looks:

    int pkt.quorum = 3;
    void signalSignedPackets(String signedPkt) {
         pkt.signedPktsList.add(signedPkt);
         pkt.quorum--;
     }

Now this setup works perfectly fine for my use case. The problem arises when I try to expand the scope of this setup i.e. downloadPacket method instead of taking 1 nodeId as input, can take a list of nodeIds as input. This would mean that downloadPacket would then return a list of packets, 1 for each node. Now the admins would be required to sign all these packets, but I don’t want the workflow to wait till each packet has received all 3 signatures. I want to implement this functionality such that the workflow waits on each packet to receive at least 3 signed packets, and as soon as it does it proceeds to upload those signed packets. In the meanwhile it could be possible that other packets have not received at least 3 signed packets, so the await call(s) keeps on waiting for them too.

Here’s my novice attempt towards a pseudo code for what I wish to achieve

Workflow.await(if (pkt1.quorum <= 0) =>  myWorkflow.uploadSignedPackets(pkt1.signedPktsList))
Workflow.await(if (pkt2.quorum <= 0) =>  myWorkflow.uploadSignedPackets(pkt2.signedPktsList))
Workflow.await(if (pkt3.quorum <= 0) =>  myWorkflow.uploadSignedPackets(pkt3.signedPktsList))

The key point here is that I wish to have the workflow waiting for all these conditions asynchronously i.e. if an admin submits all 3 signed packets for pkt2 first, but not for pkt1, it should go ahead and upload the signed packets for pkt2, and not keep on waiting for pkt1 to receive all the signed packets and only then move forwards with pkt2’s condition.

Is it possible to achieve something like this using Workflows and my current setup?

Hi @prachi, working on a small sample solution for your question. Will get back to you asap.

1 Like

Thank you @tihomir! Much appreciated :slight_smile:

@prachi Got help from @maxim to get the async part in good shape.

Here you will find a sample which implements the requirements mentioned. You can run the Starter to see it in action.
You can also play with the order of sent signals in the Starter to see that it is async as you requested.

Hope this helps

1 Like

Thank you @tihomir and @maxim for all your efforts! The implementation is awesome and works right as expected. Really grateful for the help!

2 Likes

@tihomir The implementation triggers an activity from a signal method. Is that acceptable?

Reason I am asking this question is, I remember reading it somewhere that signal methods should be used to just mutate object and they shouldn’t be used to trigger workflows or activities

I think its typically recommended not to but there are use cases where invoking activity from signal handler is easier. Just be aware of possible issues with error handling within signal handlers, for example recently resolved issue here (fix will be available in upcoming 1.18.0 java sdk release).

1 Like