首页 > 解决方案 > Azure Function App 对 Webhook 的初始响应

问题描述

我的函数应用中有一个 HTTP 触发函数 - 它由 Azure 逻辑应用中的 webhook 连接器调用。Webhook 在逻辑应用程序中的工作方式是它们需要初始响应,例如"status:200"使逻辑应用程序进入睡眠状态,然后在“工作”完成时callbackURL调用,然后逻辑应用程序恢复工作。我的问题是响应我的函数应用程序的初始响应。

如果您在 2 分钟内未使用 status:2** 响应 webhook,则 webhook “重试”会启动函数应用的新实例,这显然是有问题的。

所以我的代码看起来像这样

try 
{ 
     await function1() // this function runs more than 2 minutes
}
catch(err)
{
     context.log(err)
}
finally
{
     await function2() // this function returns to LogicApp via callbackurl
}

我尝试context.res = { status:200}在 try 块中添加并尝试创建一个context.res = {status:200}内部的单个函数,但是这些都不起作用。

如果我的函数运行不到 2 分钟,那么显然 webhook 不会重试,但是当它确实需要超过 2 分钟时它会失败。

我尝试基于本文中的“Webhook”设计进行构建

调用 Azure 长时间运行的函数

这些是我尝试过的组合:

try {
    context.bindings.res = {status:202}
    await function1()
}

try {
    context.res = {status:202}
    await function1()
}

try {
    await initialResponse(context)// function that has context.res={status:202} inside
    function1()
}

try {
    context.res = {status:202}
    context.done()
    await function1()
} // I added @UncleDave 's suggestion as well

try {
    await initialResponse(context)
    function1()
}
async function initialResponse(context)
{
    context.res = {status:202}
    context.done()
} // this attempt also just ended the function

标签: node.jsazureazure-functionswebhooksazure-logic-apps

解决方案


考虑创建第二个函数来处理长时间运行的操作并更改当前函数以将请求放入队列并立即返回。

您的 Web 挂钩命中的 HTTP 触发器:

函数.json

{
  "bindings": [
    {
      "authLevel": "anonymous", // Don't do this - demonstration only.
      "type": "httpTrigger",
      "direction": "in",
      "name": "req",
      "methods": [
        "post"
      ]
    },
    {
      "type": "http",
      "direction": "out",
      "name": "res"
    },
    {
      "type": "queue",
      "direction": "out",
      "name": "queue",
      "queueName": "process",
      "connection": "AzureWebJobsStorage"
    }
  ]
}

index.js

module.exports = function (context, req) {
  context.log('Started processing a request.', req);

  context.done(null, {
    res: { status: 202 },
    queue: { callbackUrl: req.body.callbackUrl, data: req.body.data }
  });
};

执行处理的队列触发器:

函数.json

{
  "bindings": [
    {
      "name": "item",
      "type": "queueTrigger",
      "direction": "in",
      "queueName": "process",
      "connection": "AzureWebJobsStorage"
    }
  ]
}

index.js

module.exports = async function (context, item) {
    context.log('JavaScript queue trigger function started to process work item.', item);

    const data = await process(item.data);

    const request = require('request');

    await request.post(item.callbackUrl, { body: data, json: true });
};

function process(data) {
    // Some long running operation.
    return new Promise(resolve => {
        setTimeout(() => resolve({ a: 'b', c: 'd' }), 5000);
    });
}

请注意,我在request这里使用的是外部依赖项,您必须将其添加到您package.json的 .Node 中,但 Node 内置的 HTTP 客户端也可以正常工作。


推荐阅读