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:
- 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:
ASSIGNADDSUBTRACTDIVIDEMULTIPLYEXTENDREMOVE_IF_PRESENTREMOVE_KEYREMOVE_INDEX
A description of each VariableType 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.
- Java
- Go
- Python
- C#
public void threadFunction(WorkflowThread thread) {
WfRunVariable foo = thread.declareInt("foo");
// ... optionally execute some tasks
foo.assign(3);
}
func someThreadFunction(thread *littlehorse.WorkflowThread) {
foo := thread.DeclareInt("foo")
// ... optionally execute some tasks
foo.Assign(3)
}
def thread_function(thread: WorkflowThread) -> None:
foo = thread.declare_int("foo")
# ... optionally execute some tasks
foo.assign(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();
- Java
- Go
- Python
- C#
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));
}
func someThreadFunction(thread *littlehorse.WorkflowThread) {
foo := thread.DeclareInt("foo").WithDefault(3)
taskOutput := thread.Execute("some-task-that-returns-int")
foo.Assign(foo.Add(taskOutput))
}
def thread_function(thread: WorkflowThread) -> None:
foo = thread.declare_int("foo").with_default(3)
int_output = thread.execute("some-task-that-returns-int")
foo.assign(foo.add(int_output))
static 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:
- Java
- Go
- Python
- C#
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));
}
func someThreadFunction(thread *littlehorse.WorkflowThread) {
listToAppend := thread.DeclareJsonArr("list-to-append").WithDefault([]string{"testN"})
myList := thread.DeclareJsonArr("my-list").WithDefault([]string{"test1", "test2"})
// ... execute a few tasks
myList.Assign(myList.Extend(listToAppend))
}
def thread_function(thread: WorkflowThread) -> None:
list_to_append = thread.declare_json_arr("list-to-append").with_default(["testN"])
my_list = thread.declare_json_arr("my-list").with_default(["test1", "test2", "test3"])
# ... execute a few tasks
my_list.assign(my_list.extend(list_to_append))
public void ThreadFunction(WorkflowThread thread)
{
WfRunVariable listToAppend = thread.DeclareJsonArr("list-to-append").WithDefault(new List<string> { "testN" });
WfRunVariable myList = thread.DeclareJsonArr("my-list").WithDefault(new List<string> { "test1","test2" });
// ... execute some tasks
myList.Assign(myList.Extend(listToAppend));
}
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:
- Java
- Go
- Python
- C#
public void threadFunction(WorkflowThread thread) {
WfRunVariable myVar = thread.declareJsonObj("my-var");
WfRunVariable counterPath = myVar.jsonPath("$.counter");
// ... execute some tasks
counterPath.assign(counterPath.add(1));
}
func someThread(thread *littlehorse.WorkflowThread) {
myVar := thread.DeclareJsonObj("my-var")
counterPath := myVar.JsonPath("$.counter")
// ... execute some tasks
counterPath.Assign(counterPath.Add(1))
}
def thread_function(thread: WorkflowThread) -> None:
my_var = thread.declare_json_obj("my-var")
counter_path = my_var.with_json_path("$.counter")
# ... execute some tasks
counter_path.assign(counter_path.add(1))
static void ThreadFunction(WorkflowThread thread)
{
WfRunVariable myVar = thread.DeclareJsonObj("my-var");
WfRunVariable counterPath = myVar.WithJsonPath("$.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.