试图用内联编辑器将mongoDB整合到Dialogflow中去

问题描述 投票:0回答:1

我正在尝试将mongoDB整合到Dialogflow中。更具体地说,我试图通过使用DialogFlow来改变安装在AWS EC2实例中的MongoDB数据库中一个名为'lightState'的特定数据字段的值。当我说'打开灯'时,数据'lightState'必须更新为1的值,反之则为0。

在进入真正的问题之前,我先把我的代码贴在下面。

var tunnel = require('tunnel-ssh');
var mongoLib = require('mongodb');
var config = {
    username: 'ubuntu',
    host: <my-host-ip-address>,
    port: 22,
    privateKey: <my-aws-instance-private-key>
    dstHost: '127.0.0.1',
    dstPort: 27017,
    localPort: 24800
};

const functions = require('firebase-functions');
const {WebhookClient} = require('dialogflow-fulfillment');
const {Card, Suggestion} = require('dialogflow-fulfillment');

process.env.DEBUG = 'dialogflow:debug'; // enables lib debugging statements

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => {
const agent = new WebhookClient({request, response});
console.log('Dialogflow Request headers: ' + JSON.stringify(request.headers));
console.log('Dialogflow Request body: ' + JSON.stringify(request.body));

var server = tunnel(config, function(error, server){
if(error) throw error;
else {
  if(server != null){
    var Client = mongoLib.MongoClient('mongodb://127.0.0.1:24601/',{useUnifiedTopology:true, auto_reconnect: true});
        var conn = Client.connect(function(error, client){
            if(error) console.log(error);

            function welcome(agent) {
              agent.add(`Welcome to my agent!`);
            }

            function fallback(agent) {
              agent.add(`I didn't understand`);
              agent.add(`I'm sorry, can you try again?`);
            }

      function handleOn(agent)
        {
              const state = agent.parameters.on;
              var doc = {};
              client.db('test_db').collection('light').find().toArray(function(err,docs){
                 doc = docs; //retrieve the data format
              });
              if(state == 1) client.db('test_db').collection('light').update(doc, {$set: {lightState: 1}});  //set lightState to 1 if 'on' state equals 1.       
         }


      function handleOff(agent)
         {
          const state = agent.parameters.off;
          var doc = {};
          client.db('test_db').collection('light').find().toArray(function(err,docs){
             doc = docs;
          });
          if(state == 1) client.db('test_db').collection('light').update(doc, {$set: {lightState: 0}}); //set lightState to 0 if 'off' state equals 1.
          }

    let intentMap = new Map();
    intentMap.set('Default Welcome Intent', welcome);
    intentMap.set('Default Fallback Intent', fallback);
    intentMap.set('light_On', handleOn);
    intentMap.set('light_Off', handleOff);
    agent.handleRequest(intentMap);         
      });
   }
  }
 });
});

以上是DialogFlow的Inline Editor中的代码。在Inline Editor中部署代码后,第一次要求DialogFlow打开或关闭灯光时,一切都很正常,AWS EC2的mongoDB数据库中的数据字段变化成功。但当我再次尝试要求Dialogflow开灯或关灯时,Google Cloud Console上的日志查看器会显示以下错误。

"Error: listen EADDRINUSE 127.0.0.1:24800
at Server.setupListenHandle [as _listen2] (net.js:1360:14)
at listenInCluster (net.js:1401:12)
at doListen (net.js:1510:7)
at _combinedTickCallback (internal/process/next_tick.js:142:11)
at process._tickDomainCallback (internal/process/next_tick.js:219:9)" 

我知道这意味着我有多个进程在24800端口上运行。但是我不知道如何在同一个端口24800上连续重用这个MongoDB服务器,这样我就可以多次要求DialogFlow更改MongoDB中的数据。有什么方法可以做到这一点吗?


我试着在onRequest函数运行之前启动ssh服务器。下面是一小段代码,以显示我修改的内容。

  var server = tunnel(config, function(error, server){
  exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, 
  response) => {
         ...

然而,Inline Editor似乎无法识别函数'dialogflowFirebaseFulfillment',它与事件处理函数onRequest相关联。错误日志显示如下。

 2020-05-24 18:44:49.459 JST
 dialogflowFirebaseFulfillment
 Node.js module defined by file index.js is expected to export function 
 named dialogflowFirebaseFulfillment

在尝试了上面的方法后,我想到了如果端口繁忙时动态分配端口的办法。但我找不到任何方便的方法。所以我被困在这里几个小时,试图找出错误的原因。

mongodb dialogflow dialogflow-fulfillment
1个回答
0
投票

问题是你要重新建立通往服务器内部的隧道。onRequest 处理程序。这将在每次调用webhook时进行,而不会关闭它,因此地址仍在使用中,并抛出错误。

更好的方法可能是设置 server 当函数被初始化时--所以在 onRequest 处理人:

[更新,一旦你尝试设置 server 外面 onRequest]它告诉你找不到函数的原因是因为你有了 export 回调函数中的语句 tunnel() 调用。输出必须在加载时进行,而不是在脚本执行时进行。

最简单的解决办法是 有一个回调,当你设置隧道时(或只是用它来记录成功或错误)。所以类似于

const server = tunnel(config, function(error){
  if( error ){
    console.error( "Tunnel not created: ", error );
  } else {
    console.log( "Tunnel ready" );
  }
});
exports.dialogflowFirebaseFulfillment = ...

应该在函数初始化时设置隧道。

[原注]你也可以选择在Inline Editor以外的地方运行你的webhook。如果你已经有一个运行MongoDB的主机,而且该主机有一个HTTPS服务器,并有有效的证书,你可以在那里运行你的webhook代码。

© www.soinside.com 2019 - 2024. All rights reserved.