microsoft / durabletask-java

Java SDK for Durable Functions and the Durable Task Framework
MIT License
13 stars 7 forks source link

Throwing OrchestratorBlockedException from finally block to handle any exception without interrupting orchestration flow #173

Closed SayantaBhar closed 11 months ago

SayantaBhar commented 11 months ago

We are executing no. of activities after doing some parsing and resolving dependent tasks in our orchestration function. Now, in order to perform some important clean up job, all of the above logic needs to be inside a try-catch-finally block. But as per documentation: https://learn.microsoft.com/en-us/java/api/com.microsoft.durabletask.orchestratorblockedexception?view=durabletask-java-1.x

OrchestratorBlockedException is thrown when an orchestrator calls Task#await on an uncompleted task. The purpose of throwing in this way is to halt execution of the orchestrator to save the current state and commit any side effects. Catching OrchestratorBlockedException in user code could prevent the orchestration from saving state and scheduling new tasks, resulting in the orchestration getting stuck.

Hence, had to throw exception from finally block in case of OrchestratorBlockedException was thrown like the following:

try {
            // parsing
            taskOrchestrationContext.allOf(parallelTasks).await();
            // checking what all tasks' dependant tasks are complete
            taskOrchestrationContext.createTimer(Duration.ofSeconds(5)).await();
            //
} catch (Exception e) {
            // logging error
            caughtException = e;
        } finally {
            // 
            if (caughtException instanceof OrchestratorBlockedException) {
                throw caughtException;
            } else {
                // Do some important clean up job
            }
        }

Otherwise was getting stuck with following exception

Exception occurred: The orchestrator is blocked and waiting for new inputs. This Throwable should never be caught by user code.
com.microsoft.durabletask.interruption.OrchestratorBlockedException: The orchestrator is blocked and waiting for new inputs. This Throwable should never be caught by user code.

Do you see any issue with such kind of handling? Is there any better way to handle the above mentioned situation?

kaibocai commented 11 months ago

Hi @SayantaBhar , your handling logic is correct, but it may be simplified as below. Thanks.

        try {
            // parsing
            taskOrchestrationContext.allOf(parallelTasks).await();
            // checking what all tasks' dependant tasks are complete
            taskOrchestrationContext.createTimer(Duration.ofSeconds(5)).await();
            //
        } catch (OrchestratorBlockedException e) {
            throw e;
        } catch (Exception e) {
            //logging, processing other exception. 
            // clean up
        }
SayantaBhar commented 11 months ago

Thanks @kaibocai for confirming about the handling logic. This issue can be closed now. (P.S: I need to do the clean up irrespective of exception thrown or not hence was doing like the way I have mentioned i.e inside finally block.)