Add global variables to workflows

I often have to do weird workflows in situations where I would normally use a variable with a conditional assignment. variables, like the ones in apps and modules would help simplify these parts of workflows. usually I just connect a bunch of blocks to 1 JS block named 'normalizeData' and use if/elses to return the object i want from whatever sources I connected. this way later on I can reference one block instead of using conditionals everywhere to select the .data from the correct block.

2 Likes

Hi @bobthebear, we found and existing internal FR for this. I added your +1 and feedback to it.
We'll update you here when there are any updates on it. :slightly_smiling_face:

1 Like

For now, what you are doing is the workaround. Here is another example for visualization, in case other users are looking for an implementation:

1 Like

Hi @Paulo plus one for this please!

In my situation, I want to store a JWT in a variable to be used in a loop that makes api calls. However, the token expires before the loop is finished, so I'd like to be able to check the expiry within the loop and if it's close to expiry, request a new token and update the variable.

If you think there's already a way to do this, I'd be grateful for advice!

Hi @paul_mcardle! I added your plus one. :slightly_smiling_face:
On the meantime, we should be able to return the index (and data at the index) where the error happened. Using an error handler, we could get a new token and begin a new iteration starting at the index we returned.

1 Like

@Paulo I am struggling to figure out how I can do this, and alter the value of the "variable" within the workflow. Using your example above, I am tempted to do something in query1 like set code1.data.test2 = false based on something it checks, and have subsequent code blocks now read that variable as code.data.test2 == false.

When I try that, it works within the scope of the current block. But anything after the current block goes back to the original value.

codeBlock.data is read-only, this is why code1.data.test2 = false is failing silently. It doesn't change the value. What I meant was to reference code1.data.test2 (index returned) on an error handler or another block with the goal of running a new loop, using the index to reference where to start.

However, @explore recently shared a way to trigger Workflows recursively. Maybe this is an easier implementation for your use case:

Feel free to share a screenshot of your WF, it would help us figure out the next steps. :slightly_smiling_face:

2 Likes

Hi there,
have there been any changes regarding this?
I would love to be able to define (and modify) global JavaScript variables.
I've figured out I can add 'semi-constants' to the JS Setup script, but since this is prepended to every JavaScript block separately it cannot be modified between blocks and it cannot be used in workflow functions.

1 Like

I added your +1 internally but there are no updates yet.
This featue is currently not in our roadmap.

1 Like

+1

+1 for this.

FYI - As a workaround, I found you could assign data to the workflowContext object which is accessible globally (e.g. workflowContext.globals = { foo: 42 }; for accessing a foo variable via a globals child object). You need to be careful it doesn't clash with any existing data though.

2 Likes

I didn't actually know that the workflowContext object could be written to! That's a great suggestion, @CWhite. I'm actually going to mark this as the accepted "Solution", with the caveat that it's technically a workaround. :+1:

I'll keep the topic open, though, and provide an update as soon as I have news regarding the formal feature request.

1 Like

Hi, can you give a example of setting and using the variables I tried this but had no luck

im using this to set the variable

// First, initialize workflowContext.globals if it's undefined
if (!workflowContext.globals) {
workflowContext.globals = {};
}

// Optionally set the value
workflowContext.globals.fulfillmentMethod = workflowContext.globals.fulfillmentMethod || "fbb";

// Return the value
return workflowContext.globals.fulfillmentMethod;

result: {"data":"fbb"}

then use this to return the variable

if (!workflowContext.globals) {
workflowContext.globals = {};
}
return workflowContext.globals.fulfillmentMethod || "not set";

result: {"data":"not set"}

The following setup works for me, @Gsmplus

Note that it doesn't really work when running blocks individually, but functions as expected when running the workflow as a whole. :+1:

Does this workaround work for you in a global error handler? It isn’t for me. That said, when I’m viewing “run history”, expand the global error handler block, click “Inputs”, it actually shows me the object attribute I created as a “global”. However, in the global error handler js code itself, attempt to access anything I create, comes up “undefined”.

My use-case might be helpful – I have a cron triggered workflow that does some processing of a queued up job. If the workflow fails, I want the job in the db to reflect the error. I have a global error handler that updates the job record in the table with the error and some failure status. But that update requires so table pk which I was storing using the above workaround. Unfortunately, that globals object isn’t available so I don’t know what job was being processed at the time.

That's an interesting callout, @lkiss. :thinking: I can confirm that it doesn't seem to be accessible in the disconnected global error handler, despite what the Inputs tab says. The below does work for me, though!

Essentially, I dedicate a code block to exposing the globals object so that it can later be read by the error handler.

I ran into another scenario where this isn’t working for me.

If I have a function call block that calls a single-step function that runs javascript – in the javascript, workflowContext.globals will not exist IF there is a retry on the function block. Even if first execution of of function block call would work and wouldn’t execute retry logic, that globals is still not in there. When I remove the retry, workflowContext.globals is available to me.

As a workaround, I attempted to pass in workflowContext.globals as a function parameter. This also did not work when a retry was present. I also attempted to just pass in workflowContext and that too did not work.

That's a truly bizarre edge case, @lkiss! I really don't think workflowContext is intended to be modified, though, so I'm not really surprised there is so much weirdness.

Outside of recreating the workaround that I shared above, your other option is to define the retry settings on the function itself instead of on the runFunction block.

@Darren 100% agreed. I guess I’m using this thread as an outlet to share things I’m finding as I encounter them, in hopes that others may have figured out workarounds or save others some time.

And yes, I’ve reimplemented the retry logic and it’s working well.

I haven’t tested the global error workaround you provided. Looking forward to it though!!

1 Like