puppeteer-cluster:为单个执行任务设置超时

puppeteer-cluster: Setting a timeout on individual execution tasks

我试图让个别任务在压力测试期间暂停,以查看我的调用程序将执行的操作。但是,我的集群会无限期地保持任务新鲜。它似乎将我所有的 cluster.execute 调用排队,然后将这些调用保存在内存中,并将它们的结果 return 发送给早已断开连接的听众。

文档状态:

timeout <number> Specify a timeout for all tasks. Defaults to 30000 (30 seconds).

我的集群启动配置:

const cluster = await Cluster.launch({
    concurrency: Cluster.CONCURRENCY_CONTEXT,
    maxConcurrency: 1,
    timeout: 1000 //milliseconds
});

我正在调用排队机制使用:

const pdf = await cluster.execute(html, makePdf);

其中 makePdf 是一个 async 函数,需要 HTML 字符串,用它填充页面并使用默认值 puppeteer 打印 PDF。

const makePdf = async ({ page, data: html, worker }) => {
    await page.setContent(html);
    let pdf = await page.pdf({});
    console.log('worker ' + worker.id + ' task ' + count);
    return pdf;
};

我有点希望队列开始自行清空,直到它找到一个没有超过其超时值的任务。我试过将 timeout 设置为 1 毫秒,但这也不会触发超时。我已经尝试按照示例中的描述将此代码移动到 cluster.task 以查看是否会触发设置,但没有这样的运气。如何让已经排队的请求超时?如果我不抓取网站或连接任何东西,这是否有效?

我正在考虑将时间戳与我的任务一起传递,这样它就可以跳过对调用方已过期的请求执行任何操作,但我宁愿尽可能使用内置选项。

编辑:

感谢 Thomas 的澄清,我决定构建这个小优化以防止执行监听器早已消失的任务。

data 的内容从仅 html 替换为同时具有 url 和时间戳的 json:

let timestamp = new Date();
await cluster.execute({html, timestamp});

忽略侦听器超时的任何排队任务:

const makePdf = async ({ page, data: { html, timestamp }, worker }) => {
    let time_since_call = (new Date() - timestamp);
    if (time_since_call < timeout_ms) {
        await page.setContent(html);
        let pdf = await page.pdf({});
        return pdf;
    } 
};

这是对timeout的误解。 timeout 选项是任务的超时时间,这意味着作业本身(离开队列后)不能超过指定的超时时间。该选项不会取消仍在队列中的排队作业。

示例:

const cluster = await Cluster.launch({
    // ...
    maxConcurrency: 1,
    timeout: 1000 // one second
});
// ...
for (let i = 0; i < 10; i += 1) {
    cluster.queue('...');
}

此代码添加 10 个作业并按顺序运行它们(因为 maxConcurrency1)。这里的 queueexecute 没有区别(有关此主题的更多信息,请参阅 )。那么会发生以下情况:

  • 第一份工作开始运行
  • 第一个作业在一秒后中断
  • 第二份工作开始运行
  • 第二个作业在一秒后中断
  • ...

库目前不支持您描述的用例(顺便说一句,免责声明:我是作者),但正如您所建议的,您可以向正在排队的对象添加时间戳并取消作业如果过去太远就马上。