How to retry WorkflowExecution AlreadyStarted thrown when starting child workflow?

Hi, we have a use case where we have a parent workflow starting a child workflow. The child workflow uses a specific workflow id as ‘business key’ so only one workflow execution can be running at a time for the ‘business key’. We want the parent workflow catch WorkflowExecutionAlreadyStarted exception and retry until it succeeds in starting the child workflow. What’s the recommended way to retry the child workflow in this case? I tried using Workflow.retry() which works but the workflow execution history doesn’t record the WorkflowExecutionAlreadyStarted exception at all, which makes troubleshooting difficult unless the oncall ops person is familiar how the workflow is defined. Is there a better way to implement this use case? thanks.

If this child is already a child of the same workflow then WorkflowExecutionAlreadyStarted is indeed doesn’t need to be recorded as the duplication is discovered by the SDK without consulting with the service. If the existing workflow was created by some other workflow then the local detection is not possible and the WorkflowExecutionAlreadyStarted failure will be recorded in the history.

No, the existing child is started by a different parent workflow. Here’s the setup.

ParentWorkflowType

  • workflowId A
  • workflowId B

ChildWorkflowType

  • workflowId X

both A and B are trying to start ChildWorkflowType with ‘X’ as the workflowId. one of them (say A) will succeed, the other will get WorkflowExecutionAlreadyStarted failure. we want the ParentWorkflowType to retry on that failure so the B can start ChildWorkflowType with ‘X’ after the execution started by A is complete

I cannot imagine the situation when this is not recorded in the workflow execution history. Could you post one of the parent that received WorkflowExecutionAlreadyStarted and it wasn’t recorded?

My mistake, not sure how I missed the StartChildWorkflowExecutionFailed event. I see them in the history now. Thanks for looking into this Maxim.

I’d also want to wrap the WorkflowExecutionAlreadyStarted error and rethrow as a retryable failure. Here’s the workflow code of the parent:

    @Override
    public void startWorkflow(WorkflowInput input) {
        Workflow.retry(
            childWfRetryOptions,
            Optional.empty(),
            () -> startChildWorkflow(input));
    }

    private void startChildWorkflow(WorkflowInput input) {
        String businessKey = createBusinessKey(input);
        ChildWorkflowOptions options = ChildWorkflowOptions.newBuilder()
            .setTaskQueue(WorkflowConstants.DEFAULT_TASK_QUEUE)
            .setWorkflowId(createBusinessKey(input))
            .build();
        ChildWorkflow childWf = Workflow.newChildWorkflowStub(ChildWorkflow.class, options);
        try {
            log.info("Starting child workflow for {}", input);
            childWf.startWorkflow(createChildWorkflowInput(input));
        } catch (ChildWorkflowFailure e) {
            Throwable rootCause = ExceptionUtils.getRootCause(e);
            if (rootCause instanceof WorkflowExecutionAlreadyStarted) {
                throw ApplicationFailure.newFailureWithCause(
                    String.format("A child workflow with the business key %s already exists. " +
                            "System will retry after some time", businessKey),
                    "AlreadyProcessingBusinessKey",
                    rootCause);
            }
            throw e;
        }
    }

I’d want to see the custom failure message in the event history. is that something that can be done ?

@davidc

I don’t see it possible with Workflow.retry, the exception is handled internally and is not propagated.

It will only rethrow the exception when shouldRethrow (eg: maxAttempts reached etc… ), which will fail the workflow.

Update: we are looking into this with the SDK team to verify whether this is the expected behaviour