private tryResumingUserCode()

in src/orchestrations/TaskOrchestrationExecutor.ts [354:424]


    private tryResumingUserCode(): void {
        // If the current task does not have a result,
        // then we cannot continue running the user code.
        const currentTask: TaskBase = this.currentTask;
        this.context.isReplaying = currentTask.isPlayed;
        if (currentTask.stateObj === TaskState.Running) {
            return;
        }

        // We feed in the result of the current task to the generator
        let newTask: TaskBase | undefined = undefined;
        try {
            // In the WhenAny-case, the result of the current task is another Task.
            // Here, we make sure not to expose the internal task class by extracting
            // the user-facing representation of the task.
            const result = currentTask.result;
            const taskValue = result;
            const taskSucceeded = currentTask.stateObj === TaskState.Completed;

            // If the task succeeded, we feed the task result as a value;
            // otherwise, we feed it as an exception.
            const generatorResult = taskSucceeded
                ? this.generator.next(taskValue)
                : this.generator.throw(taskValue);

            if (generatorResult.done) {
                // If the generator returned (via a `return` statement),
                // then we capture the workflow's result result.
                this.orchestratorReturned = true;
                this.output = generatorResult.value;
                return;
            } else if (generatorResult.value instanceof DFTask) {
                // The generator yielded another task.
                newTask = generatorResult.value;
            } else {
                // non-task was yielded. This isn't supported
                let errorMsg = `Durable Functions programming constraint violation: Orchestration yielded data of type ${typeof generatorResult.value}.`;
                errorMsg +=
                    typeof generatorResult.value === "undefined"
                        ? ' This is likely a result of yielding a "fire-and-forget API" such as signalEntity or continueAsNew.' +
                          " These APIs should not be yielded as they are not blocking operations. Please remove the yield statement preceding those invocations." +
                          " If you are not calling those APIs, p"
                        : " Only Task types can be yielded. P";
                errorMsg +=
                    "lease check your yield statements to make sure you only yield Task types resulting from calling Durable Functions APIs.";

                throw Error(errorMsg);
            }
        } catch (exception) {
            // The generator threw an exception
            this.exception = exception;
        }

        if (newTask !== undefined) {
            // The generator returned an already-completed task,
            // so we try to run the user code again.
            this.currentTask = newTask;
            if (newTask.state !== TaskState.Running) {
                this.tryResumingUserCode();
            } else {
                // The task hasn't completed, we add it to the open (incomplete) task list
                this.trackOpenTask(newTask);
                // We only keep track of actions from user-declared tasks, not from
                // tasks generated internally to facilitate history-processing.
                if (this.currentTask instanceof DFTask && !this.currentTask.alreadyScheduled) {
                    this.markAsScheduled(this.currentTask);
                    this.addToActions(this.currentTask.actionObj);
                }
            }
        }
    }