Skip to main content
Version: Next

Mutating Variables

Recall from the Concepts Documentation that every Node can have zero or more VariableMutations on it. A VariableMutation changes the value of a ThreadRun's Variables.

You can add a VariableMutation at any point in your Thread Function by using the WfRunVariable#assign() method or function.

Basic Structure

The WfRunVariable::assign() functions/methods take one argument:

  1. A WfRunVariable, NodeOutput, Object/interface/struct, or primitive type to serve as the RHS for the mutation.

The valid Mutation Types come from the VariableMutationType enum and are:

  • ASSIGN
  • ADD
  • SUBTRACT
  • DIVIDE
  • MULTIPLY
  • EXTEND
  • REMOVE_IF_PRESENT
  • REMOVE_INDEX
  • REMOVE_KEY
  • AND
  • OR
  • POW

A description of each VariableMutationType can be found on the protobuf documentation.

Examples

Here are some examples of mutating variables inside a WfSpec.

Hard-Coded Literal Value

Let's assign our variable foo to the hard-coded value of 3.

public void threadFunction(WorkflowThread thread) {
WfRunVariable foo = thread.declareInt("foo");
// ... optionally execute some tasks
foo.assign(3);
}

Using a NodeOutput

Let's say we have a TaskDef which returns an INT value, and we want to add that value to our WfRunVariable. To do that, we use the NodeOutput as the RHS.

This is analogous to the following pseudocode.

int myInt = 1;
myInt += doTask1();
public void threadFunction(WorkflowThread thread) {
WfRunVariable foo = thread.declareInt("foo").withDefault(3);
NodeOutput intOutput = thread.execute("some-task-that-returns-int");
foo.assign(foo.add(intOutput));
}

Using other WfRunVariables

We can also use another WfRunVariable as the RHS. For example, if our LHS is a JSON_ARR, we can append another JSON_ARR to it as follows:

public void threadFunction(WorkflowThread thread) {
WfRunVariable listToAppend = thread.declareJsonArr("list-to-append").withDefault(Arrays.asList("testN"));
WfRunVariable myList = thread.declareJsonArr("my-list").withDefault(Arrays.asList("test1", "test2"));

// ... execute some tasks

myList.assign(myList.extend(listToAppend));
}

Using .get()

You can use the .get() method to access fields and list elements of your variables.

Usage

If your LHS variable is of type Struct or JSON_OBJ, you can use .get("fieldName") to access a specific field of the object.

If your LHS variable is of type Array or JSON_ARR, you can use .get(index) to access a specific element of the list.

The Struct and Array types provide PutWfSpecRequest-time type safety, while the JSON_OBJ and JSON_ARR types are more flexible but lack type safety, crashing your WfRun at runtime if you try to access a field that doesn't exist or is of the wrong type.

Example

If your LHS variable is of type Struct or JSON_OBJ, you can use WfRunVariable#get() to allow you to mutate a specific sub-field of your object or list. For example, if I have a my-var Struct variable as follows:

@Getter
@Setter
@LHStructDef("car")
public class Car {
String make;
String model;
int year;

public Car () {}
}

and I want to increment the year field, I can do so as follows:

public void threadFunction(WorkflowThread thread) {
WfRunVariable myVar = thread.declareStruct("my-car", Car.class).required();
WfRunVariable yearPath = myVar.get("year");

// ... execute some tasks

yearPath.assign(yearPath.add(1));
}

Using JsonPath

Both NodeOutput and WfRunVariable have a #jsonPath() method.

If your LHS variable is of type JSON_ARR or JSON_OBJ, you can use WfRunVariable#jsonPath() to allow you to mutate a specific sub-field of your object or list. For example, if I have a my-var variable as follows:

{
"foo": "bar",
"counter": 123
}

and I want to increment the counter field, I can do so as follows:

public void threadFunction(WorkflowThread thread) {
WfRunVariable myVar = thread.declareJsonObj("my-var");
WfRunVariable counterPath = myVar.jsonPath("$.counter");

// ... execute some tasks

counterPath.assign(counterPath.add(1));
}

You can also use .jsonPath() on the RHS to pick out a specific field of your RHS value.

Mutating Arrays

The native ARRAY type supports several mutation operations, including a SIZE_OF unary operation for getting the number of elements in an Array. For more details on declaring and using arrays, see the Arrays concepts page.

Extending an Array

Use extend() to append a single element to an ARRAY. The element is type-checked against the array's declared element type.

public void threadFunction(WorkflowThread thread) {
WfRunVariable arrVar = thread.declareArray("my-array", Long.class);

// Append a value to the array
arrVar.assign(arrVar.extend(4L));
}

Removing Elements

Use removeIfPresent() to remove all occurrences of a value, or removeIndex() to remove the element at a specific position.

public void threadFunction(WorkflowThread thread) {
WfRunVariable arrVar = thread.declareArray("my-array", Long.class);

// Remove all occurrences of value 2
arrVar.assign(arrVar.removeIfPresent(2L));

// Remove the element at index 0
arrVar.assign(arrVar.removeIndex(0));
}
warning

The ADD, SUBTRACT, MULTIPLY, DIVIDE, and REMOVE_KEY operations are not valid for ARRAY variables and will be rejected during WfSpec registration.