What is the best way to access and modify object in Parent Workflow from Child Workflow

Usecase
I have an object in my Parent Workflow. And I have a couple of child workflows which need to access and update this object. Also note, I can have my child workflows running parallely.

Current Approach

  1. I have a query method in parent class to expose this object to child Workflows.

  2. I have a signal method in parent class to let child worklfows to update the object via signal

  3. To summarize, Childworkflows invoke the query method and get hold of the object, they modify the object and invoke the signal method to have it updated in parent workflow

Problem
Signal method is not working. It throws “Potential Deadlock detected, workflow thread - “workflow method” didn’t yield any result”.

Questions

  1. Is this an expected behaviour? Can’t child workflows signl Parent Workflow?

  2. Are signals and queries the right way to deal with shared state between Parent and Child workflows?

  3. As all the child workflows will be executed by one thread, is there a need to have explicit synchronization in place? If one of the child workflow is updating the shared Object X, should we lock it to prevent other workflow from doing the same?

Querying child workflows directly from a workflow code is not supported. You have to use an activity as using a WorkflowClient inside the workflow code is prohibited.

Maxim, I’m able to query without any issue.
I’m able to query the Parent Workflow method from Child Workflow.
I’m using the workflowClient inside the child workflow to create a stub of Parent workflow and then calling the query method on the stub.

Whats not working is signal method.

Did you mean signaling parent workflow from child worklfow is not allowed?

I’m using the workflowClient inside the child workflow to create a stub of Parent workflow and then calling the query method on the stub.

Any direct calls to any services are explicitly prohibited from the workflow code. WorkflowClient talks to Temporal gRPC endpoint directly, so it is also prohibited. See Workflow Implmentation Contstraints section of the documentation for the list of constraints inside the workflow code.

Thanks Maxim, moving the update logic to activity fixed the issue.

My activites now, procure the object from Parent workflow via query and update it back via signal.

Given that I have multiple activites running in parallel and doing this update on the same parent workflow, do I need do any explicit syncronization in the parent workflow similar to this (Thread Syncronization when using Async.function inside a Workflow - #2 by maxim).

There is no need for synchronization as all signals are serialized in the history and processed one by one.

Given that I use Query + Signal, does that change the need for synchronization?

Example
objectValue = 0

activity 1 queries, gets objectValue as 0
activity 2 queries, gets objectValue as 0

activity 1 increments objectValue from 0 to 1 and signals back to parent as 1
activity 2 increments objectValue from 0 to 1 and signals back to parent as 1

In reality the objectValue should be 2 after the two updates. But it will be 1.

I see. This is not really a synchronization issue as query and signal are absolutely independent from the Temporal point of view. You have to deal with this in the application code.


@maxim

I’m finding it hard to write the synchronizatin snippet. I have attached the use case diagram.

I have 3 different types of child workflows. All the 3 different workflows have their own workers.
My Main workflows invokes these 3 child workflows parallely.

The child workflows once they are done with their work, they have an activity to pass on the details back to the mail workflow. In that activity, I’m getting the object from main worklfow via query method. And then updating it and passing it back to the main workflow via signal.

Requirement
The object O must be accessed via query and updated via signal by only one child workflow at a time.
As explained in the last reply, to prevent the race condition, Only after the first child workflow is completed with its update, the next child worklfow should query to get the object.

What I have tried
I tried maintaining a flag in the main workflow.
This flag will be set to true when some workflow is accessing the Object.
Once that childworkflow has completed the update, this flag will be set to false.

So when a childworkflow sees this flag as false, it needs to wait untill it is set to true.

The child workflows needs to be inimated about the state change instead of them quering to know each and every time. This is where it starts to get complicated.

Is there a better way to do it?

I’m not convinced that the child workflow querying the parent and then updating it through a signal is the best option. But I don’t know your use case, so I cannot propose an alternative.

If you really want to do a query then update this then you’ll have to do something like:

  • query workflow for the object. The result of the query should include the object version.
  • Send signal with the update which includes the object version and the client id.
  • query workflow for the updated version. If the version and the client id are of the client that sent the request then the update went through. If the version and client don’t match then the update was rejected and should be reexecuted.

Maxim,
How about queries?
Are they executed one by one?
Or if mulitple workers are available to fullfill the query, it is done in parallel?

Queries are executed one by one.