microsoft / botbuilder-dotnet

Welcome to the Bot Framework SDK for .NET repository, which is the home for the libraries and packages that enable developers to build sophisticated bot applications using .NET.
https://github.com/Microsoft/botframework
MIT License
864 stars 480 forks source link

Waterfall steps are being called out of order #6754

Open gmantri opened 4 months ago

gmantri commented 4 months ago

Github issues should be used for bugs and feature requests. Use Stack Overflow for general "how-to" questions.

Version

Microsoft.Bot.Builder.Dialogs: 4.21.2 Microsoft.Bot.Builder.Integration.AspNet.Core: 4.21.2

Describe the bug

Cross-posting from StackOverflow: https://stackoverflow.com/questions/78064646/botframework-net-waterfall-steps-are-being-called-out-of-order


We are using BotFramework SDK version 4 (.Net) for our Teams Chatbot. Our code makes use of Waterfall dialog. Generally the code is working fine but randomly we are seeing some odd behavior. What we are noticing is that the waterfall steps are being executed out of order.

Our waterfall dialog is pretty straightforward:

  1. Step1: Start of dialog. It invokes the login OAuth dialog.
  2. Step2: Processes the response of login OAuth dialog and calls Step3.
  3. Step3: Processes the user's message and generates a response.

Here's the pseudo-code for our dialog:

public class MyDialog : ComponentDialog
{
    private readonly OAuthPrompt _loginOAuthPrompt;
    private const string LoginOAuthPromptName = "LoginOAuthPrompt";

    public MyDialog()
    {
        _loginOAuthPrompt = new OAuthPrompt(
            LoginOAuthPromptName,
            new OAuthPromptSettings
            {
                ConnectionName = "ConnectionName",
                Text = "Please Sign In",
                Title = "Sign In",
                Timeout = 30000, // User has 5 minutes to login (1000 * 60 * 5)
                EndOnInvalidMessage = true
            });
        AddDialog(_loginOAuthPrompt);
        AddDialog(new WaterfallDialog(nameof(WaterfallDialog), new WaterfallStep[]
        {
            Step1Async,
            Step2Async,
            Step3Async,
        }));

        InitialDialogId = nameof(WaterfallDialog);
    }

    private async Task<DialogTurnResult> Step1Async(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        _logger.LogInformation($"MyDialog:Step1Async()called. Step context index: {stepContext.Index}; Reason: {stepContext.Reason}.");
        return await stepContext.BeginDialogAsync(LoginOAuthPromptName, null, cancellationToken);
    }

    private async Task<DialogTurnResult> Step2Async(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        _logger.LogInformation($"MyDialog:Step2Async()called. Step context index: {stepContext.Index}; Reason: {stepContext.Reason}.");
        //do something with the result of login oauth prompt dialog
        return await stepContext.NextAsync(stepContext, cancellationToken);
    }

    private async Task<DialogTurnResult> Step3Async(WaterfallStepContext stepContext, CancellationToken cancellationToken)
    {
        _logger.LogInformation($"MyDialog:Step3Async()called. Step context index: {stepContext.Index}; Reason: {stepContext.Reason}.");
        //process business logic
        return await stepContext.CancelAllDialogsAsync(cancellationToken: cancellationToken);
    }
}

If all works well, we see the following output in our logs:

MyDialog:Step1Async()called. Step context index: 0; Reason: BeginCalled.
MyDialog:Step2Async()called. Step context index: 1; Reason: EndCalled.
MyDialog:Step3Async()called. Step context index: 2; Reason: NextCalled.

However, randomly we are noticing that when a user sends a message to the chatbot, instead of calling Step1Async, it calls Step2Async. At times it would call Step1Async however the stepContext.Index value will be either 1 or 2 (instead of 0 and the reason would be EndCalled instead of BeginCalled.

We are not able to figure out why this is happening. For many conversations these steps will be executed perfectly but then all of a sudden a random step will be picked up.

Any insights into this behavior will be highly appreciated.

To Reproduce

Unfortunately there is no set way to consistently reproduce this behavior.

Expected behavior

The dialog should follow the same steps always.