Hello Users,
Platform provides Service Nodes for calling external APIs. But it has a maximum timeout of 20 seconds.
For some APIs however it may take more than 20 seconds to respond. Though, as per industry standards, APIs are expected to have a average response times of about 6 seconds.
I want to walk you through a way you can use web-hook node and BotKit to resolve a response which could take more than 20 seconds.
Note: Web-Hook node supports a timeout of up to 10 minutes. But if you use it in synchronous way (example - FindFlight.js on our BotKit GitHub repository) Platform will still timeout in 20 seconds on Kore cloud platform.
You will need to use asynchronous way (as explained in BookACab.js on our BotKit GitHub repository)
Below is another simple working code which you can use for test.
Note - We are using setTimeout function along with service call to a delay API. setTimeout will add bulk of the time. In below example, setTimeOut waits for 30 seconds while delay API adds 5 seconds delay.
Firstly you need to have redis for this. Ensure redis is running (default port 6379)
Then in botkit’s config.json have the following configuration:
"redis": {
"options": {
"host": "localhost",
"port": 6379
},
"available": true
},
Then you will need to have a js file like the below registered in app.js.
sdk.registerBot(require('./CustomBotkitWebHookNodeDemo.js'));
It is assumed that the bot will have a webhook node with name hookCallAPIFromBotkit.
Note the usage of
callback(null, new sdk.AsyncResponse());
AsyncResponse() tells the platform to wait for the response to be sent asynchronously.
and within
sdk.saveData(requestId, data)
the respond to hook will send the data back.
sdk.respondToHook(data);
In bot, based on the following code, the data from web-hook node will be available in
context.endPointResp
var botId = "st-XXXXXXX-XXX-XX";
var botName = "webhookDemoBot";
var sdk = require("./lib/sdk");
var Promise = sdk.Promise;
var request = require("request");
var config = require("./config");
//Make request to service app
function callAPIEndPoint(api) {
var serviceUrl = undefined;
if(api){
serviceUrl = api;
} else {
serviceUrl = 'https://httpbin.org/delay/5';
}
console.log("callAPIEndPoint is calling URL " + serviceUrl);
return new Promise(function(resolve, reject) {
request({
url: serviceUrl,
method: 'get',
}, function(err, res) {
if (err) {
return reject(err);
}
resolve(JSON.parse(res.body));
});
});
}
module.exports = {
botId : botId,
botName : botName,
on_user_message : function(requestId, data, callback) {
sdk.sendBotMessage(data, callback);
console.log("###request id: " + requestId);
console.log("on_user_message ==> " + data.message);
},
on_bot_message : function(requestId, data, callback) {
sdk.sendUserMessage(data, callback);
console.log("###request id: " + requestId);
console.log("on_bot_message ==> " + data.message);
},
on_webhook : function(requestId, data, componentName, callback) {
console.log("###request id: " + requestId);
var context = data.context;
if (componentName === 'hookCallAPIFromBotkit') {
var api = null;
console.log("on_webhook ==> calling API for hookCallAPIFromBotkit");
console.log("wait on... " + new Date());
sdk.saveData(requestId, data)
.then(function() {
setTimeout(function(){
callAPIEndPoint(api).then(function(endPointResp) {
data.context.endPointResp = endPointResp;
sdk.respondToHook(data);
console.log("wait done... " + new Date());
});
},30000);
callback(null, new sdk.AsyncResponse());
});
}
},
on_agent_transfer : function(requestId, data, callback){
return callback(null, data);
}
};
Output of botkit console:
Bot output
Message Node settings: