我有两个函数,scheduleScan()
和scan()
。
当除了安排新的扫描无需执行其他任何操作时,scan()
会调用scheduleScan()
,因此scheduleScan()
可以计划scan()
。但是有一个问题,有些作业要运行两次。
我想确保在任何给定时间仅处理一项作业。我该如何实现?我相信这与done()
有关,(它在scan()中,现在已删除),但我无法提出解决方案。
公牛版:3.12.1
重要的后期编辑: scan()
调用另一个函数,它们可能会或可能不会调用其他函数,但是它们都是同步函数,因此它们仅在完成自己的作业时才调用一个函数,只有一种方法。我在“树”的末尾调用它,最后一个函数调用scheduleScan(),但是不能同时运行两个作业。顺便说一句,每个作业都以scan()
开始,以scheduleScan(stock, period, milliseconds, 'called by file.js')
结尾export function update(job) {
// does some calculations, then it may call scheduleScan() or
// it may call another function, and that could be the one calling
// scheduleScan() function.
// For instance, a function like finalize()
}
export function scan(job) {
update(job)
}
import moment from 'moment'
import stringHash from 'string-hash'
const opts = { redis: { port: 6379, host: '127.0.0.1', password: mypassword' } }
let queue = new Queue('scan', opts)
queue.process(1, (job) => {
job.progress(100).then(() => {
scan(job)
})
})
export function scheduleScan (stock, period, milliseconds, triggeredBy) {
let uniqueId = stringHash(stock + ':' + period)
queue.getJob(uniqueId).then(job => {
if (!job) {
if (milliseconds) {
queue.add({ stock, period, triggeredBy }, { delay: milliseconds, jobId: uniqueId }).then(() => {
// console.log('Added with ms: ' + stock + ' ' + period)
}).catch(err => {
if (err) {
console.log('Can not add because it exists ' + new Date())
}
})
} else {
queue.add({ stock, period, triggeredBy }, { jobId: uniqueId }).then(() => {
// console.log('Added without ms: ' + stock + ' ' + period)
}).catch(err => {
if (err) {
console.log('Can not add because it exists ' + new Date())
}
})
}
} else {
job.getState().then(state => {
if (state === 'completed') {
job.remove().then(() => {
if (milliseconds) {
queue.add({ stock, period, triggeredBy }, { delay: milliseconds, jobId: uniqueId }).then(() => {
// console.log('Added with ms: ' + stock + ' ' + period)
}).catch(err => {
if (err) {
console.log('Can not add because it exists ' + new Date())
}
})
} else {
queue.add({ stock, period, triggeredBy }, { jobId: uniqueId }).then(() => {
// console.log('Added without ms: ' + stock + ' ' + period)
}).catch(err => {
if (err) {
console.log('Can not add because it exists ' + new Date())
}
})
}
}).catch(err => {
if (err) {
// console.log(err)
}
})
}
}).catch(err => {
// console.log(err)
})
}
})
}
最佳答案
我相信这个问题是您的scan
函数是异步的。因此,您的job.progress
函数调用scan
,然后立即调用done
,以允许队列处理其他作业。
一种解决方案是将done
回调作为参数传递给scan
和scheduleScan
函数,并在完成工作(或出现错误)后调用它。
另一个(更好)的解决方案可能是确保始终从Promise
和scan
返回scheduleScan
,然后等待 promise 解决,然后调用done
。如果这样做,请确保在scheduleScan
函数中链接所有 promise 返回。
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;
})
}
关于javascript - 如何确保某项工作在Bull中不会执行两次?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/60042303/