Search code examples
reactjsbotframeworkazure-bot-servicespfxweb-chat

BotFramework ReactWebChat With DirectLineAppServiceExtension getting repeated welcome message on specific time interval


I have C# SDK based azure bot developed and deployed on azure, this bot is using Language(Custom Question Answering) service for answering users questions.

The front end part is a SPFX React WebChat which suppose to be a webpart of another sharepoint site.

The bot is working fine in Emulator or in Test WebChat(In portal) but i am facing issue about repeated welcome message when running it from spfx react webchat.

The process for React Webchat is as follow:

  1. On componentDidmount() hook i request token for Direct Line :

    public async componentDidMount() {
    this.fetchToken();
    }

     private async fetchToken() {  
         var myToken ='<<--Secret Key-->>';  
           const res = await fetch('https://xxxx.azurewebsites.net/api/GetLRToken', 
         { method: 'GET',
           headers: {'accept': 'application/json'}  
         });
         var { token } = await res.json();
         console.log(token);  
         this.setState({  
             directLine: await createDirectLineAppServiceExtension({
             domain: 'https://xxxx.azurewebsites.net/.bot/v3/directline',
             token,
           }),
         });  
         this.state.directLine.postActivity({  
           from: { id: "serId", name: "USER_NAME" },  
           name: "requestWelcomeDialog",  
           type: "event",  
           value: "token"  
         }).subscribe(  
           id => console.log(`Posted activity, assigned ID ${id}`),  
           error => console.log(`Error posting activity ${error}`)  
         );  
    
       } 
    

Which successfully fetches the token.

  1. On public render(): React.ReactElement Method i load <ReactWebChat directLine={this.state.directLine} which is wrapped under Panel (Office UI Fabric panel)

  2. In the Bot Source code on OnMembersAddedAsync method i compare added member id with turnContext recipient id as shown below and if not same i show Welcome card (Adaptive card):

    protected override async Task OnMembersAddedAsync(IList membersAdded, ITurnContext turnContext, CancellationToken cancellationToken) {

                 foreach (var member in membersAdded)
                 {
                     if (member.Id != turnContext.Activity.Recipient.Id)
                     {
                        await SendWelcomeMessageAsync(turnContext, cancellationToken);
                     }
                 }
    
         }
    

This whole process and communication with bot works absolutely fine but i am unable to trace down issue why welcome screen is getting repeatedly loading our periodic time.

one observation during debugging i found is member.id is the GUID i have generated during token generation process and turncontext receipent id is something different like xxx-bot-t-xxs@kTXXB7DBjMs which seems to be a app service@some random id and i really dont know how that is being generated.

Hence it could be reason compare case always fails and shows the welcome card.

Any help to streamline the process highly appreciate, as i am new to SPFX and specially React, i dont know how to control client side code.

For reference i have attached screenshot here. Thank you in advance.enter image description here


Solution

  • According to Microsoft this timeout of 230 secs is part of the app service Load Balancer configuration, and it cannot be altered. The same timeout window applies for WebSocket connections as well. It is for HTTP triggered function but also applicable for Azure App Service.

    Azure Load Balancer has a default idle timeout setting of four minutes. This setting is generally a reasonable response time limit for a web request. so, App Service returns a timeout to the client if your application does not return a response within approximately 240 seconds (230 seconds on Windows app, 240 seconds on Linux app)

    Official Documentation : Why does my request time out after 230 seconds?

    So below code will be helpful for you,

    let activity: EventActivity = { type: 'event', name: 'eventName', value: null, from: null };
    setInterval(() => { this.directLine.postActivity(activity).subscribe() }, 200000);
    

    This will basically send a blank/dummy activity after every 200 seconds which prevents a timeout.