Loop until condition is met

I’d like to implement a “loop until” in a workflow.

The loop will include a time delay and a collection fetch action. I want to loop until a condition is met based on a field value in the fetched collection.

Of course also want to build in a timeout to avoid infinite looping.

How do I set my loop config to do something like this?

Open to better ways to handle what I need:

  • when backend process is complete (status field is marked “complete”), exit workflow

Thanks!

Wouldn’t it be better just for your backend workflow to send a “success” response when the status is marked complete?

A loop on the front end would strain the user’s browser resource I think.

Not the most efficient, but given that there seems to be no websocket support in WeWeb, you could probably do a for loop and add a time delay in the loop.

Your timeout would be (time delay) * (length of the array). The array could be anything (like [0, 1… 100]).

Yeah, I like that thought given the lack of websocket support.

FWIW, my current workaround is to notify the user via slack DM once the process is completed running in the backend. The DM includes a link to the page that contains the next step (the one that I’d use a “Change Page” action to if I were able to do this all in a workflow.

Don’t love it but actually not terrible for my use case.

Its possible to do a loopUntil workflow, but it requires a bit of javascript

Create a variable to handle your loop timeout reference (I usually call them timeout with a prefix to precise the logic/functonality of it or put it in a folder)

Create a global workflow:

  • First action must cancel the previous loop (i will come back to that later). We use a customjs action with the following code
    clearTimeout(variables.timeout) (with variables.timeout being the variable you created before). This is not mandatory, but it can avoid to start too many loop in parallel ny mistake

  • Next action being a filter action checking your stop action (like your receive a status ok)

  • Next actions will handle your logic

  • The last action will be a customJS action, with the following code (this will start the loop)
    variables.timeout = setTimeout(() => { executeWorkflow(workflowId) }, 2000)

    • Last parameter (2000) is the interval in milliseconds of your timeout, up to you to pick a good value depending on your usecase. Too much will flood your server, not enough will delay the user experience
    • Workflow id is the id of your workflow, you can have it display by activating the dev information (on the dev panel

You can have a variation of this with a setInterval logic.

We know this is not ideal, but this kind of logic can lead to important bugs (infinite loop, server flooding), so we really want to think about it before making it to easy to push by mistake. But we are aware of this usecase, and working on it :slight_smile:

Also please be sure that if you go this way, you must be very vigilant that one day your condition will be met, or you will have infinite loop. By security you can add a maximum number of tries or times on the condition.

2 Likes

Also, if you have the possibility to have websockets, its always better.

1 Like

@aurelie what’s the status of executeWorkflow?
Should we consider it safe to use or is it in the category of things that are not officially supported and may break in the future?

this has been added recently to be officially used :slight_smile:
It can also be usefull for integration with third parties

2 Likes

Thanks for the detailed reply, @aurelie! I’ll keep this in mind for future use cases.

Hoping for a bit of help on this one - seems simple enough but I’m not able to get the loop working.

I think my problem is around creating the timeout variable. I have called my variable ‘Var_Timeout’, and the UID is ‘ecb2a707-0c8c-4491-a901-df304c97c236’. My variable is of a number type - I’m not sure if this matters, or if this is even the correct way to have created the variable. (I have since tried all types and none seem to work.)

The first action in my global workflow is the following Custom JS:
clearTimeout(variables['ecb2a707-0c8c-4491-a901-df304c97c236'])

I then fetch a collection and do a true/false to check to see whether I can end the loop. If the condition hasn’t been satisfied, I increment a counter (also part of the condition to avoid an infinite loop), and then run the following Custom JS:
variables['ecb2a707-0c8c-4491-a901-df304c97c236'] = setTimeout(() => { executeWorkflow('31b4820b-1082-44d4-88ef-76fd2aa253bb') }, 1000)

My counter is getting to 1, so the loop isn’t triggering.

And this is my workflow:

I’m sure it’s something straightforward, so any help would be appreciated.

Hey @ilan, could you share the content inside of each action?

Sure thing @Quentin.

Custom JavaScript at the top:
clearTimeout(variables['ecb2a707-0c8c-4491-a901-df304c97c236'])

Fetch collection:
sheety_DecUpdating.Get

True/false split:
if(variables['e95979ec-946c-49bc-841e-0f802fa265ac']>10,false,true)

True (first step):
variables['e95979ec-946c-49bc-841e-0f802fa265ac']+1

True (second step):
variables['ecb2a707-0c8c-4491-a901-df304c97c236'] = setTimeout(() => { executeWorkflow('31b4820b-1082-44d4-88ef-76fd2aa253bb') }, 1000)

False:
Change variables[‘e95979ec-946c-49bc-841e-0f802fa265ac’] to 1111

When this is all working, I’ll add into the condition a test on the fetched collection (i.e., has it been updated). For the moment, I’ve dropped that condition because I want to see whether ‘e95979ec-946c-49bc-841e-0f802fa265ac’ (Var_Counter) loops 10 times to know that the loop in the workflow is working. The last false variable change is just so I could see the loop on the front-end, but it never gets there… (Also, in the screenshot from my previous post I realise I had the wrong variable in the false branch - I’ve changed this to Var_Counter and it makes no difference as it never gets to the false branch because the true 2nd step doesn’t restart the workflow).

Thanks!