Botframework-sdk: How to set a timeout in one waterfall step and clear it in the next one

Created on 11 Jan 2017  路  2Comments  路  Source: microsoft/botframework-sdk

Hey , first of all, hats off for the fabulous work in this library. I have a quiz game that uses prompts and I want to ask the person to answer if they dont reply to a question in say 4 mins. For each question, I want to set a timeout and clear the timeout if the person answers or fire the timeout whichever comes first. The code below gives me an error

bot.dialog('/', [(session)=>{
    ...
    session.dialogData.inactive = setTimeout(()=>{
        session.send('You there?')
    },240000)
    ...
}, (session, results)=>{
...
        clearTimeout(session.dialogData.inactive)
...
}])
TypeError: Converting circular structure to JSON
    at Object.stringify (native)
    at addWrite (D:\bots\zupquiz\node_modules\botbuilder\lib\bots\ChatConnector.js:261:29)
    at ChatConnector.saveData (D:\bots\zupquiz\node_modules\botbuilder\lib\bots\ChatConnector.js:276:21)
    at D:\bots\zupquiz\node_modules\botbuilder\lib\bots\UniversalBot.js:405:21
    at UniversalBot.tryCatch (D:\bots\zupquiz\node_modules\botbuilder\lib\bots\UniversalBot.js:425:13)
    at UniversalBot.saveStorageData (D:\bots\zupquiz\node_modules\botbuilder\lib\bots\UniversalBot.js:402:14)
    at Object.onSave (D:\bots\zupquiz\node_modules\botbuilder\lib\bots\UniversalBot.js:266:27)
    at Session.sendBatch (D:\bots\zupquiz\node_modules\botbuilder\lib\Session.js:381:22)
    at Timeout.<anonymous> (D:\bots\zupquiz\node_modules\botbuilder\lib\Session.js:513:23)
    at ontimeout (timers.js:365:14)
    at tryOnTimeout (timers.js:237:5)
    at Timer.listOnTimeout (timers.js:207:5)

How can I achieve this effect?

Most helpful comment

So in general you should think about this problem a little differently. The question you need to ask is do you want to send the user a message if they haven't answered within 4 minutes or do you want to simply say they took to long if they answer after 4 minutes? The second approach is easier then the first...

Your bot should generally try to remain stateless meaning you don't want to start a bunch of timers and such in your bot. The error you saw is because you tried to store a timer handle in your bots data bag which isn't going to work because it can't be properly serialized. Only simple types can be remembered.

The simplest approach to your problem is to store a timestamp for when you sent the user a question and then tell them they took long if they answer comes back more than 4 minutes later. Completely stateless approach to the problem and no timers needed.

If you want to get fancy and send them a message telling them they're taking to long you'll need to send a proactive message to the user using a distributed timer of some sort like Azure Scheduler. The key is you need to be able to start a timer that you can cancel when you receive the answer. That's simple to do if your bot runs on a single compute node (look at the basics-NaturalLanguage example for a simple in-memory scheduler) but is more complicated if your bot spans multiple nodes.

Hope that made sense and helps...

All 2 comments

So in general you should think about this problem a little differently. The question you need to ask is do you want to send the user a message if they haven't answered within 4 minutes or do you want to simply say they took to long if they answer after 4 minutes? The second approach is easier then the first...

Your bot should generally try to remain stateless meaning you don't want to start a bunch of timers and such in your bot. The error you saw is because you tried to store a timer handle in your bots data bag which isn't going to work because it can't be properly serialized. Only simple types can be remembered.

The simplest approach to your problem is to store a timestamp for when you sent the user a question and then tell them they took long if they answer comes back more than 4 minutes later. Completely stateless approach to the problem and no timers needed.

If you want to get fancy and send them a message telling them they're taking to long you'll need to send a proactive message to the user using a distributed timer of some sort like Azure Scheduler. The key is you need to be able to start a timer that you can cancel when you receive the answer. That's simple to do if your bot runs on a single compute node (look at the basics-NaturalLanguage example for a simple in-memory scheduler) but is more complicated if your bot spans multiple nodes.

Hope that made sense and helps...

Thank you for the detailed insight! I ll find another way

Was this page helpful?
0 / 5 - 0 ratings