首页 > 解决方案 > 延迟 koa 请求 30 分钟但立即发送 200 头

问题描述

我希望将所有请求延迟到最初收到端点的 30 分钟后。我正在使用 Shopify 并正在响应订单创建 webhook,将数据传递给另一个 3rd 方服务。

这就是发生的情况:下订单,然后通过 Shopify 触发一个 webhook,它使用关联的订单数据联系我的 koa 端点。

我想立即接收 webhook 正文(其中包括订单数据),然后等待 30 分钟,然后将该信息发送到另一个服务。但是我想立即将 200 标头发送回 Shopify,无论代码在 30 分钟延迟后是否正确执行(如果没有,我将通过错误电子邮件通知我,并且可以手动处理,这不会是世界末日)。

我已经尝试过setTimeout方法,但问题似乎是这样的:直到 30 分钟结束后,我才能将 200 标头发送回 Shopify(或者我不应该,根据 Koa 文档?)。

意思是,如果我做类似的事情

context.response.status = 200; // tried to send response code immediately due to 30 minute timeout.
await handleRequest(context.request.body); // code waits 30 mins via settimeout

200 标头没有立即发送

30 分钟过去了,Shopify 早就放弃接收 200 标头并自动将请求放入重试队列,这意味着 webhook 将在 30 分钟结束之前再次触发,所以我将发送重复对我尝试等待 30 分钟的服务的请求。

我考虑过 cron,但并不是我希望每 30 分钟处理一次,我希望每个单独的请求在收到后等待 30 分钟发送到第三方服务。

我真的想避免使用数据库。

setTimeout如果有办法在超时和 30 分钟后的后续服务调用之前将 200 标头发送回 Shopify,我可以使用。

标签: node.jsshopifywebhookskoa

解决方案


状态码与 HTTP 消息的第一部分一起出现,因此您需要开始发送或结束 HTTP 响应。

在这种情况下,您无需阻止对第 3 方呼叫的响应。将您想在 30 分钟内运行的逻辑移到它自己的函数中,不要等待计时器。您的响应逻辑中不需要它。

一些伪代码:

function talkTo3rdPartyDelayed(context, delay) {
    setTimeout(()=>{
        // talk to 3rdparty
    }, delay);
    return; // continue what you were doing before, this is non-blocking
}

function listenForShopify(req, res, next) {
    talkTo3rdPartyDelayed({req.body}, 30*60*1000);
    res.statusCode = 200;
    next(); // or res.end() which sends the status code
}

顺便说一句,在一个强大的系统中,您可以将希望延迟 30 分钟的第 3 方请求存储在队列系统中,并将可见性计时器设置为提前 30 分钟。这样,如果流程终止,您就不会失去您打算做的工作。必须手动处理出现的任何问题都会让人厌烦。


推荐阅读