[英]Initial Response to Webhook from Azure Function App
I have a HTTP triggered function inside my function app - it is invoked by the webhook connector in Azure Logic Apps.我的函数应用中有一个 HTTP 触发的函数 - 它由 Azure 逻辑应用中的 webhook 连接器调用。 The way webhooks work in Logic Apps is they need the initial response like
"status:200"
which puts the Logic App to sleep and then when the "work" is done the callbackURL
is invoked and then the Logic App resumes work. Webhooks 在逻辑应用程序中的工作方式是,它们需要初始响应,例如
"status:200"
,它使逻辑应用程序进入睡眠状态,然后在“工作”完成时调用callbackURL
,然后逻辑应用程序恢复工作。 My problem is responding with that initial response from my function app.我的问题是响应我的函数应用程序的初始响应。
If you don't respond to the webhook with a status:2** within 2 minutes then the webhook "retries" which starts a new instance of the function app and that is obviously problematic.如果您没有在 2 分钟内以 status:2** 响应 webhook,则 webhook 会“重试”,这会启动函数应用程序的新实例,这显然是有问题的。
So my code looks something like this所以我的代码看起来像这样
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
}
I have tried adding context.res = { status:200}
in the try block and have tried creating an individual function that has context.res = {status:200}
inside, however none of those work.我尝试在 try 块中添加
context.res = { status:200}
并尝试创建一个内部具有context.res = {status:200}
的单个函数,但是这些都不起作用。
If my function runs under 2 minutes then obviously the webhook doesn't retry, however when it does take over 2 minutes it fails.如果我的函数在 2 分钟内运行,那么显然 webhook 不会重试,但是当它花费超过 2 分钟时它会失败。
I tried to build based on the "Webhook" design from this article我尝试基于本文中的“Webhook”设计进行构建
Calling Long Running Functions Azure 调用长时间运行的函数 Azure
These are the combinations I have tried:这些是我尝试过的组合:
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
Consider creating a second function to handle the long running operation and change your current function to throw the request on to a queue and immediately return.考虑创建第二个函数来处理长时间运行的操作并更改当前函数以将请求放入队列并立即返回。
function.json函数.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索引.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 }
});
};
function.json函数.json
{
"bindings": [
{
"name": "item",
"type": "queueTrigger",
"direction": "in",
"queueName": "process",
"connection": "AzureWebJobsStorage"
}
]
}
index.js索引.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);
});
}
Note that I'm using request
here, which is an external dependency you'll have to add to your package.json
, but Node's built in HTTP Client will work just as well.请注意,我在这里使用了
request
,这是您必须添加到package.json
的外部依赖项,但 Node 内置的 HTTP 客户端也可以正常工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.