Javascript 我如何才能确保一份工作不会';不要在公牛中跑两次?

Javascript 我如何才能确保一份工作不会';不要在公牛中跑两次?,javascript,node.js,bull.js,Javascript,Node.js,Bull.js,我有两个函数,scheduleScan()和scan() scan()。但有一个问题,有些作业会运行两次 我想确保在任何给定时间只处理一个作业。我怎样才能做到这一点?我相信它与done(),(它在scan()中,现在被删除)有关,但我无法想出解决方案 牛版:3.12.1 重要的后期编辑:scan()调用另一个函数,它们可能调用也可能不调用其他函数,但它们都是同步函数,因此它们只在自己的作业完成时调用函数,前进的路只有一条。在“树”的末尾,我调用它,最后一个函数调用scheduleScan(),但

我有两个函数,
scheduleScan()
scan()

scan()。但有一个问题,有些作业会运行两次

我想确保在任何给定时间只处理一个作业。我怎样才能做到这一点?我相信它与
done()
,(它在scan()中,现在被删除)有关,但我无法想出解决方案

牛版:3.12.1

重要的后期编辑:
scan()
调用另一个函数,它们可能调用也可能不调用其他函数,但它们都是同步函数,因此它们只在自己的作业完成时调用函数,前进的路只有一条。在“树”的末尾,我调用它,最后一个函数调用scheduleScan(),但不能同时运行两个作业。顺便说一句,每个作业都从
scan()
开始,然后以
scheduleScan(股票、周期、毫秒,'called by file.js')结束。


问题是,我相信您的
扫描
函数是异步的。因此,您的
job.progress
函数调用
scan
,然后立即调用
done
,允许队列处理另一个作业

一种解决方案是,将
done
回调作为参数传递给
scan
scheduleScan
函数,并在完成作业后(或出现错误时)调用它

另一个(更好的)解决方案是确保始终从
scan
scheduleScan
返回
Promise
,然后等待Promise解决,然后调用
done
。如果执行此操作,请确保在
scheduleScan
函数中链接所有承诺返回

queue.process(1, (job, done) => {
  job.progress(100).then(() => {
    scan(job)
        .then(done)
        .catch(done)
  })
})

export function scan() {
   // business logic
   return scheduleScan()
}

// Chain all of your promise returns. Otherwise
// the scan function will return sooner and allow done to be called
// prior to the scheduleScan function finishing it's execution
export function scheduleScan() {
    return queue.getJob(..).then(() => {
        ....
        return queue.add()...
        ....
        return queue.add(...)
            .catch(e => {
                 console.log(e);
                 // propogate errors!
                 throw e;
             })

}

扫描函数是一个异步函数。在
queue.process()
函数中,必须等待scan函数,然后调用
done()
回调函数

export async function scan(job) {
  // it does some calculations, then it creates a new schedule.
  return scheduleScan(stock, period, milliseconds, "scan.js");
}

queue.process(1, (job, done) => {
  job.progress(100).then(async() => {
    await scan(job);
    done();
  });
});

export async function scheduleScan(stock, period, milliseconds, triggeredBy) {
    let uniqueId = stringHash(stock + ":" + period);
    try {
      const existingJob = await queue.getJob(uniqueId);
      if (!existingJob) {
        const job = await addJob({
          queue,
          stock,
          period,
          uniqueId,
          milliseconds,
          triggeredBy
        });
        return job;
      } else {
        const jobState = await existingJob.getState();
        if (jobState === "completed") {
          await existingJob.remove();
          const newJob = await addJob({
            queue,
            stock,
            period,
            uniqueId,
            milliseconds,
            triggeredBy
          });
          return newJob;
        }
      }
    } catch (err) {
      throw new Error(err);
    }
}

export function addJob({ queue, stock, period, milliseconds, triggeredBy }) {
  if (milliseconds) {
    return queue.add(
      { stock, period, triggeredBy },
      { delay: milliseconds, jobId: uniqueId }
    );
  } else {
    return queue.add({ stock, period, triggeredBy }, { jobId: uniqueId });
  }
}

试试这个!我尝试使用async Wait重构代码。

我找不到
扫描
函数,你能帮忙吗?@MuhammadZeeshan我添加了它,我的错误。我编辑了我的问题,你能不能再检查一遍,尤其是“重要的后期编辑”部分?你的答案在这种情况下仍然适用吗?谢谢。是的,它仍然有效。从您的编辑中,我想您是说,
scheduledScan
总是在
scan
中的所有其他同步函数之后调用。如果是这样,那么是的,我的回答仍然有效。只要始终返回将从
scan
functionalgain中的
scheduleScan
返回的承诺,我的错误。第一个函数update()在扫描中,但是update()可以调用另一个函数,如finalize(),finalize()可以调用scheduleScan()。请记住,这些都是按顺序发生的,所以没有多次呼叫,我这样做是为了让我的应用程序模块化谢谢,同样的回答。如果
update
调用
scheduledScan
或它们之间的任意数量的函数。关键的一点是,您需要将承诺链从
scheduleScan
返回到
scan
函数。因此,如果
scan
调用
update
哪个调用
finalize
。。。。。哪些调用
scheduleScan
承诺链需要通过所有函数调用返回,也就是说,请确保您从每个函数返回承诺。因此,请澄清我最后的评论。例如,如果内部扫描调用update。您需要从扫描功能返回更新结果(承诺)。我已经编辑了我的问题,请您再次检查,特别是“重要的延迟编辑”部分?你的答案在这种情况下仍然适用吗?谢谢
export async function scan(job) {
  // it does some calculations, then it creates a new schedule.
  return scheduleScan(stock, period, milliseconds, "scan.js");
}

queue.process(1, (job, done) => {
  job.progress(100).then(async() => {
    await scan(job);
    done();
  });
});

export async function scheduleScan(stock, period, milliseconds, triggeredBy) {
    let uniqueId = stringHash(stock + ":" + period);
    try {
      const existingJob = await queue.getJob(uniqueId);
      if (!existingJob) {
        const job = await addJob({
          queue,
          stock,
          period,
          uniqueId,
          milliseconds,
          triggeredBy
        });
        return job;
      } else {
        const jobState = await existingJob.getState();
        if (jobState === "completed") {
          await existingJob.remove();
          const newJob = await addJob({
            queue,
            stock,
            period,
            uniqueId,
            milliseconds,
            triggeredBy
          });
          return newJob;
        }
      }
    } catch (err) {
      throw new Error(err);
    }
}

export function addJob({ queue, stock, period, milliseconds, triggeredBy }) {
  if (milliseconds) {
    return queue.add(
      { stock, period, triggeredBy },
      { delay: milliseconds, jobId: uniqueId }
    );
  } else {
    return queue.add({ stock, period, triggeredBy }, { jobId: uniqueId });
  }
}