TWILIO:使用 "evaluateWorkerAttributes" 过滤任务队列导致超时错误

TWILIO : Filtering TaskQueues with "evaluateWorkerAttributes" resulting in Time Out error

每当我尝试过滤 TaskQueues 时,我都会遇到 "runtime application timed out" 错误。这是完整的场景。

在 twilio flex 接触板上,我必须显示代理所属的所有任务队列中待处理任务的累计计数。为此,我编写了一个 twilio 函数,它将工人技能作为输入,并根据提供的技能过滤任务队列,并对待处理任务进行计数。我遵循了提供的 twilio 文档 here。 我尝试了不同的方式来编写表达式,但最终都导致超时错误。

工人属性定义如下

{
  "routing": {
    "skills": [
      "German",
      "English",
      "French"
    ],
    "domains": [
      "ABC"
    ],
    "categories": [
      "XYZ"
    ],
    "levels": {
      "XYZ": 34
    },
    "platforms": [
      "Platform1"
    ],
    "provider": "Provider_1"
  },
  "full_name": "XXXXXXX",
  "image_url": "https:\/\/www.avatar.co\/avatar\/91f0e496?d=mp",
  "roles": [
    "admin",
    "wfo.full_access"
  ],
  "contact_uri": "client:XXX.YYYY",
  "disabled_skills": {
    "skills": [],
    "levels": {}
  },
  "email": "test@email.com"
}

在过滤队列的代码片段下方。

const TokenValidator = require('twilio-flex-token-validator').functionValidator;

const WORKSPACE_ID = 'WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
const workerSkills = ['English','French'];
console.log('SKILLS IN FUNC : ' + `routing.skills IN [${workerSkills}]`);
const getQueues = (client) => {
    return new Promise ((resolve, reject) => {
        client.taskrouter.v1.workspaces(WORKSPACE_ID)
        .taskQueues 
        .list({evaluateWorkerAttributes:'{"routing.skills" : "${workerSkills}" }',
        //.list({evaluateWorkerAttributes:"routing.skills HAS 'French'",
            limit: 1000
        })
        .then(taskQueues => resolve(taskQueues))
    });
}

const getQueueRealTimeStatistics = (client, queueID) => {
    return new Promise ((resolve, reject) => {
        client.taskrouter.v1.workspaces(WORKSPACE_ID)
        .taskQueues(queueID)
        .realTimeStatistics()
        .fetch()
        .then(realTimeStatistics => resolve(realTimeStatistics))
    });
}

exports.handler = function(context, event, callback) {
    const client = context.getTwilioClient();
    let pendingTasks = 0;
    const promises = [];
    const response = new Twilio.Response();
    response.appendHeader('Access-Control-Allow-Origin', '*');
    response.appendHeader('Access-Control-Allow-Methods', 'OPTIONS POST GET');
    response.appendHeader('Access-Control-Allow-Headers', 'Content-Type');
    response.appendHeader('Content-Type', 'application/json');
    
    getQueues(client).then(res => res.forEach(x => {
        promises.push(getQueueRealTimeStatistics(client, x.sid));
        console.log('queueID : ' + x.sid);
    })).then(x => {
        Promise.all(promises).then(res => {
            
        res.forEach(y => {
            pendingTasks = pendingTasks+ parseInt(y.tasksByStatus.pending,10);
        })
           //response.setBody(pendingTasks);
           response.setBody(pendingTasks + parseInt(res, 10));
        })
        .then(x => callback(null, response))
        .catch(err => {
            console.log(err.message);
            response.appendHeader('Content-Type', 'plain/text');
            response.setBody(err.message);
            response.setStatusCode(500);
            // If there's an error, send an error response
            // Keep using the response object for CORS purposes
            callback(null, response);
        });  
    })
};

谁能帮忙解决这个问题。提前致谢。

这里是 Twilio 开发人员布道者。

看起来你的函数大部分都写对了,应该 return。我认为有两件事可能会出错。

真的超时了

我不确定你有多少个队列,但是获取所有队列然后获取每个队列的所有统计信息可能只是将你的函数推送到 10 second limit for Function execution. If that is the case, then may have to break up the Function so that it can run within the time. Are you able to run this locally (using the Twilio Serverless Toolkit) 并且它成功了吗?

有一个错误没有被捕获并且承诺没有解决

你的代码在我看来是正确的,但是你将 API 调用的结果包装在一个新的承诺中意味着如果有错误,包装承诺永远不会解决或拒绝。这意味着函数会挂起等待结果,直到发生超时。

事实是,您不需要将 API 调用包装在新的 Promise 中,它们已经 return Promise。

我会尝试像这样重写它,避免使用新的 Promise 包装器,然后查看是否存在您没有捕捉到的错误。您还可以避免将 promises 推入数组并直接跳入 Promise.all

const TokenValidator = require("twilio-flex-token-validator").functionValidator;

const WORKSPACE_ID = "WSXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const workerSkills = ["English", "French"];
console.log("SKILLS IN FUNC : " + `routing.skills IN [${workerSkills}]`);
const getQueues = (client) => {
  return client.taskrouter.v1.workspaces(WORKSPACE_ID).taskQueues.list({
    evaluateWorkerAttributes: '{"routing.skills" : "${workerSkills}" }',
    //.list({evaluateWorkerAttributes:"routing.skills HAS 'French'",
    limit: 1000,
  });
};

const getQueueRealTimeStatistics = (client, queueID) => {
  return client.taskrouter.v1
    .workspaces(WORKSPACE_ID)
    .taskQueues(queueID)
    .realTimeStatistics()
    .fetch();
};

exports.handler = function (context, event, callback) {
  const client = context.getTwilioClient();
  let pendingTasks = 0;
  const response = new Twilio.Response();
  response.appendHeader("Access-Control-Allow-Origin", "*");
  response.appendHeader("Access-Control-Allow-Methods", "OPTIONS POST GET");
  response.appendHeader("Access-Control-Allow-Headers", "Content-Type");
  response.appendHeader("Content-Type", "application/json");

  getQueues(client)
    .then((queues) => {
      return Promise.all(
        queues.map((queue) => {
          console.log("queueID : " + queue.sid);
          return getQueueRealTimeStatistics(client, queue.sid);
        })
      );
    })
    .then((queueStats) => {
      queueStats.forEach((queueStat) => {
        pendingTasks = pendingTasks + parseInt(queueStat.tasksByStatus.pending, 10);
      });
      response.setBody({ pendingTasks });
    })
    .then(() => callback(null, response))
    .catch((err) => {
      console.log(err.message);
      response.appendHeader("Content-Type", "plain/text");
      response.setBody(err.message);
      response.setStatusCode(500);
      // If there's an error, send an error response
      // Keep using the response object for CORS purposes
      callback(null, response);
    });
};

这样做也减少了一些嵌套。如果有帮助,请告诉我。