How can workflow detect itself stuck in a state for too long

I’m writing a workflow for e-commerce order. The workflow get updates from the signal methods and move the status of the order.
Also there are multiple status for the order, like “financial_status” (pending payment, partially paid, fully paid, etc) and “shipping_status” (scheduled, fulfilled, in transit, delivered, etc)
For each stage of each status, we need to be able to detect that the workflow has been stuck in this status for too long. For example financial_status did not reached paid after 3 hours, or shipping_status did not reach in transit after 5 days. And when those happens, we don’t want the workflow to fail, but send out a notification and also mark the workflow with a search attribute to surface it on some UI.
How can we achieve this? The only way I thought of is have the workflow wake up all the time to check, which feels very wasteful and not scalable.
Thank you very much!

I assume that you are using JavaSDK. The simplest way to achieve what you want is to use Workflow.await. Something like:

Workflow.await(stateTimeout, () -> state == PENDING);

Thank you @maxim.
I don’t think I can do this with multiple status

Workflow.await(stateTimeout1, () -> state1 == PENDING);
Workflow.await(stateTimeout2, () -> state2 == PENDING);

The workflow will stuck at the first line right?

I don’t understand the question. The await condition can be any expression you want.

We have multiple status for the order, like “financial_status” (pending payment, partially paid, fully paid, etc) and “shipping_status” (scheduled, fulfilled, in transit, delivered, etc). They move forward separately.

And for each status, the timeout is a configuration or calculation based on other things. It is dynamic. For example if an order is very expensive, the financial_status can take longer to complete. If an order contains a special item, the shipping_status must take less time to complete.

So the workflow need to wait on multiple things and if any of them took too long, it needs to send notification accordingly.

I see. I think the following should work for you:

Workflow.await(min(state1Timeout, state2Timeout), 
    ()->state1 == PENDING || state2 == PENDING);

Is there a generic solution?
So we got a dynamic list, that a workflow should reach certain state after some amount of time and if the workflow did not reach the state, alert or do something or change certain flag of the workflow.
Can we tell the workflow to sleep and wake up multiple times based on a list of timestamp that the workflow should wake up, and after wake up execute the corresponding code?

Also there is a twist to my specific implementation: instead of signal, my currently implementation have the order workflow wake up every hour and query the db to check if the order status changed. So if I want to notify user an order passed some deadline, it can only happen at the hour when the workflow woke up to check new status, I cannot notify immediately when that deadline is reached

Hi @maxim,

I just had an idea. Should we create child workflow for each condition and have the child workflow sleep x amount of time, woke up and query the parent workflow status and do its thing? I feel this can be a clean implementation. However we need to cancel child workflow if the parent workflow reached the desired status before the deadline. I believe this is doable through signal.

Is there a generic solution?

Temporal workflows are code and your requirements are very specific to your use case. So just implement them using OO and other techniques.

Can we tell the workflow to sleep and wake up multiple times based on a list of timestamps that the workflow should wake up, and after wake up execute the corresponding code?

I would keep the timestamps in the sorted list and call Workflow.await with timeout that corresponds to the closest timestamp.

my currently implementation have the order workflow wake up every hour and query the db to check if the order status changed.

Make sure that the interval passed to the await is a minimum of one hour or whatever next timestamp in the list.

I just had an idea. Should we create child workflow for each condition and have the child workflow sleep x amount of time, woke up and query the parent workflow status and do its thing?

IMHO it is going to complicate the code without any clear benefit. In general, child workflows increase complexity, not reduce it as they make communication between different parts of the workflow more complicated.

1 Like