Order of execution - workflow task vs signal

Hi,

Although I think I understand the general concepts of events, tasks, signals in context of Temporal, I do not understand the order in which code is executed. I would therefore really appreciate your help in understanding the behaviour based on the code / example below.

Say I have the following (pseudo)code:

@Override // - WorkflowMethod
public void start(WorkflowInputData inputData) {
    ...
    myPartialState = EDITABLE;
    ...
    myPartialState = internalOrExternalMethod.createStatePossiblyBasedOnActivities(); // method has multiple lines, returns NOT_EDITABLE
}

@Override // - SignalMethod
public void updateState(SomeState partialState) {
    if (myPartialState.equals(EDITABLE) {
        otherPartialState = partialState;
    }
}

So the signal may arrive before the internalOrExternalMethod or after it. The signal may also arrive in any period of time when the method is being invoked. This method can be defined in the same class (with the workflow definition) or in a separate one (for separation of concerns).
I understand that the signal creates an event which then creates a task to be executed. I do not know however when this task is going to be executed, how is it scheduled in reference to the other code in the workflow.

So my main question is - can a signal code be handled between any 2 arbitrary statements in workflow code? If so, are those only internal statements that are taken into consideration (defined in the @WorkflowMethod) or any external methods as well? What constitutes a workflow task here (if anything) - is the call to the method createStatePossiblyBasedOnActivities a task, or is every statement in that method a task, or is is (possibly) everything between two activities, blocking workflow statements a task? When can I assume that the task created based on the singal to be executed? What if createStatePossiblyBasedOnActivities contains a loop and takes a while (I understand it should rather be an activity then) to go through it - will the signal be handled in between the loops execution?

And what I’m really after is - if the signal arrives while the method is being invoked - am I to assume that the myPartialState in Signal method will be equal to NOT_EDITABLE, or that it will be EDITABLE or that it depends / may be either?

Temporal uses cooperative multithreading. So a thread cannot be forcefully preempted unless it blocks on one of the Temporal APIs which include activity invocation, child workflow invocation, Promise.get, etc. So if createStatePossiblyBasedOnActivities calls one or more activities then signals callback can be called while it is blocked on one of them. If its loop just computes some data without calling into Temporal APIs then it is not going to be preempted.

2 Likes

I appreciate your quick answer, that clears it up for me, thank you!

Hi @maxim - I’m not sure I should open a separate thread for this, I have a somewhat related question.

If I have a part of Worfklow code, a method foo, invoked multiple times in a loop with Async.function(this::foo, bar), should I then assume that there is actually only one thread operating on the workflow code inside this foo method, and only if one of the statements in that method is blocking (like an activity), only then other threads can start processing through that method? So basically Asynch could be understood like asynch processing **only** during blocking calls.

In other case I’m curious how one could synchronize the state of the workflow between those Async.function invocations.

So basically Asynch could be understood like asynch processing **only** during blocking calls .

Correct.

In other case I’m curious how one could synchronize the state of the workflow between those Async.function invocations.

No need to synchronize. Even more, synchronization is prohibited in the workflow code as it can lead to deadlocks.

1 Like

Thank you @maxim