elsa-workflows / elsa-core

A .NET workflows library
https://v3.elsaworkflows.io/
MIT License
6.23k stars 1.13k forks source link

workflowRunner.RunAsync is not retuning Result when trying to resume workflow. #5072

Open TejashRaghav opened 5 months ago

TejashRaghav commented 5 months ago

I am trying to resume workflow and get result of Result variable on it.

using below code to resume workflow for specific InstanceId,BookmarkId

   var options = new WorkflowInstanceFilter
   {
       Id = InstanceId,
   };
   var workflowInstance = await _workflowInstanceStore.FindAsync(options);
   var workflowState = workflowInstance.WorkflowState;
   var workflow = await _workflowBuilderFactory.CreateBuilder().BuildWorkflowAsync<ApprovalWorkflow>();        
   var bookmark = workflowInstance.WorkflowState.Bookmarks;
   var runoption = new RunWorkflowOptions();

   foreach (var item in bookmark)
   {
       if (((Elsa.Workflows.Runtime.Bookmarks.EventBookmarkPayload)item.Payload).EventName == respose)
       {
           runoption.BookmarkId = item.Id; 
           break;
       }
   }
  var result= await _workflowRunner.RunAsync(workflow,workflowState,runoption);
  var res = **result.Result**;

My Workflow is look like:

public class ApprovalWorkflow : WorkflowBase<ProgramDetail>
{
    protected override void Build(IWorkflowBuilder builder)
    {
        var approvedVariable = builder.WithVariable<bool>();
        var sum = builder.WithVariable<IEnumerable<ProgramDetail>>().WithMemoryStorage();

        var FetchPrograms = new FetchPrograms(sum);
        builder.Root = new Sequence
        {
            Activities =
            {
                new Fork
                {
                    JoinMode = ForkJoinMode.WaitAll,
                    Branches =
                    {
                        new Sequence
                        {
                            Activities =
                            {
                               new Fork
                                {
                                    JoinMode = ForkJoinMode.WaitAny,
                                    Branches =
                                    {
                                        // Approve
                                        new Sequence
                                        {
                                            Activities =
                                            {
                                                new Event("Approve"),
                                                new SetVariable
                                                {
                                                    Variable = approvedVariable,
                                                    Value = new(true)
                                                }
                                            }
                                        },

                                        // Reject
                                        new Sequence
                                        {
                                            Activities =
                                            {
                                                new Event("Reject"),
                                                new SetVariable
                                                {
                                                    Variable = approvedVariable,
                                                    Value = new(false)
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        },
                    }
                },

                new WriteLine(context => $"Approved: {approvedVariable.Get<bool>(context)}"),
                new If(context => approvedVariable.Get<bool>(context))
                {
                    Then = new Sequence
                        {
                            Activities =
                            {
                                new WriteLine("If condition started!"),
                                FetchPrograms,
                                new WriteLine(context => $"value : {sum.Get(context).First().ProgramCode }"),
                                new SetVariable
                                {
                                    Variable = Result,
                                    Value = new (context => sum.Get(context).First()),

                                }
    }
                        },
                    Else =
                            new WriteHttpResponse
                                 {
                                 Content = new("Request rejected!"),
                                }
                }
            }

        };

    }
}

In Sum, Getting result from CodeActivity but same i not able to get it . I didn't find relevant sample example which will resume workflow and return result. Additionally, Flow is resume the request received the response but in response Result is null,

glime-ai[bot] commented 5 months ago

To resume a workflow and retrieve the result of a specific variable after the workflow has been resumed, you need to ensure that the workflow is properly resumed with the correct bookmark and that you are accessing the result from the WorkflowExecutionContext after the workflow has been resumed.

Based on the code you've provided, it seems you are trying to resume a workflow using a bookmark that corresponds to an event with a specific name (respose). After resuming the workflow, you are attempting to access the result of the workflow execution.

However, there is a mistake in the way you are trying to access the result. The result variable in your code is of type RunWorkflowResult, which does not have a Result property. Instead, you should access the Output property of the WorkflowExecutionContext to get the result of the workflow.

Here's how you can modify your code to access the result after resuming the workflow:

// ... (previous code to resume the workflow)

// Resume the workflow.
var runResult = await _workflowRunner.RunAsync(workflow, workflowState, runoption);

// Access the result from the WorkflowExecutionContext's Output property.
var workflowExecutionContext = runResult.WorkflowExecutionContext;
var resultVariable = workflowExecutionContext.Output["ResultVariableName"]; // Replace "ResultVariableName" with the actual name of your result variable.

// Do something with the result.
// ...

Make sure to replace "ResultVariableName" with the actual name of the variable you are using to store the result in your workflow.

If you are still facing issues, please ensure that:

  1. The workflow is correctly suspended and waiting for an event with the bookmark.
  2. The event name (respose) matches the event expected by the bookmark.
  3. The workflow is correctly resumed and the activities after the bookmark are executed.
  4. The variable you are trying to access as the result is correctly set in the workflow definition.

If you need further assistance, please provide more details about the specific issue you are encountering, such as any errors or unexpected behavior. Additionally, ensure that you are using the correct version of Elsa and that your workflow definition is set up to produce the expected result.

TejashRaghav commented 5 months ago
var runResult = await _workflowRunner.RunAsync(workflow, workflowState, runoption);
runResult is a type of Task<RunWorkflowResult> 

which is not contains property runResult.WorkflowExecutionContext;


/// <summary>
/// Contains information about a workflow run, such as <see cref="WorkflowState"/>.
/// </summary>
public record RunWorkflowResult(WorkflowState WorkflowState, Workflow Workflow, object? Result);

var result = workflow.ResultVariable?.Get(workflowExecutionContext.MemoryRegister);
await _notificationSender.SendAsync(new WorkflowExecuted(workflow, workflowState, workflowExecutionContext), systemCancellationToken);
return new RunWorkflowResult(workflowState, workflowExecutionContext.Workflow, result);