Eu tenho duas funções scheduleScan()
e scan()
.
scan()
chamadas scheduleScan()
quando não há mais nada a fazer, exceto agendar uma nova verificação , para que scheduleScan()
possa agendar a scan()
. Mas há um problema, alguns trabalhos são executados duas vezes.
Quero garantir que apenas um trabalho esteja sendo processado a qualquer momento. Como posso conseguir isso? Acredito que tenha algo a ver com done()
(estava em scan (), removido agora), mas não consegui encontrar uma solução.
Versão Bull: 3.12.1
Edição tardia importante: scan()
chama outras funções e elas podem ou não chamar outras funções, mas todas são funções de sincronização; portanto, elas só chamam uma função quando seus próprios trabalhos são concluídos; existe apenas um caminho a seguir. No final da "árvore", eu chamo, a última função chama scheduleScan (), mas não pode haver dois trabalhos simultâneos em execução. Todo trabalho começa às scan()
, a propósito, e termina comscheduleScan(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)
})
}
})
}
fonte
scan
função, você pode ajudar?Respostas:
O problema, acredito, é que sua
scan
função é assíncrona. Portanto, suajob.progress
função chamascan
e chama imediatamente,done
permitindo que a fila processe outro trabalho.Uma solução poderia ser a de passar o
done
retorno de chamada como um parâmetro para o seuscan
escheduleScan
funções, e invocá-lo, depois de ter concluído o seu trabalho (ou em caso de erro).Outro (melhor) solução poderia ser a de garantir que você sempre voltar a
Promise
partir descan
escheduleScan
espere a promessa de resolver e depois ligardone
. Ao fazer isso, certifique-se de encadear todos os retornos de sua promessa em suascheduleScan
função.fonte
scheduledScan
sempre é chamado depois de todas as outras funções de sincronizaçãoscan
. Se for esse o caso, então sim, minha resposta ainda é válida. Sempre retorne sempre a promessa que será retornadascheduleScan
nascan
funçãoupdate
chamadasscheduledScan
ou qualquer número de funções entre eles. O ponto principal é que você precisa retornar a cadeia de promessas descheduleScan
volta àscan
função. Portanto, se asscan
chamadasupdate
que chamamfinalise
..... As chamadasscheduleScan
da cadeia de promessas precisarão ser retornadas através de todas as chamadas de função, ou seja, apenas certifique-se de retornar a promessa de cada uma dessas funções.A função de verificação é uma função assíncrona. Na sua
queue.process()
função, é necessário aguardar a função de digitalização e, em seguida, chamar odone()
retorno de chamada.Tente isso! Eu tentei refatorar o código um pouco usando async-waitit.
fonte