Tengo dos funciones, scheduleScan()y scan().
scan()llama scheduleScan() cuando no hay nada más que hacer, excepto programar una nueva exploración , por lo que scheduleScan()puede programar una scan(). Pero hay un problema, algunos trabajos se ejecutan dos veces.
Quiero asegurarme de que solo se esté procesando un trabajo en un momento dado. ¿Cómo puedo lograr eso? Creo que tiene algo que ver con done()(estaba en scan (), eliminado ahora) pero no pude encontrar una solución.
Versión Bull: 3.12.1
Edición tardía importante: scan() llama a otras funciones y pueden o no llamar a otras funciones, pero todas son funciones de sincronización, por lo que solo llaman a una función cuando se completan sus propios trabajos, solo hay una forma de avanzar. Al final del "árbol", lo llamo, la última función llama a scheduleScan (), pero no puede haber dos trabajos simultáneos en ejecución. Cada trabajo comienza en scan(), por cierto, y termina conscheduleScan(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)
})
}
})
}
fuente

scanfunción, ¿pueden ayudarme?Respuestas:
El problema, creo es que su
scanfunción es asíncrona. Entonces sujob.progressfunción llamascany luego llama inmediatamentedonepermitiendo que la cola procese otro trabajo.Una solución podría ser pasar la
donedevolución de llamada como parámetro a suscanyscheduleScanfunciones, e invocar, una vez que haya completado su trabajo (o en caso de error).Otra (mejor) solución podría ser asegurarse de que siempre devuelva un
PromisedesdescanyscheduleScanluego esperar la promesa de resolver y luego llamardone. Si hace esto, asegúrese de encadenar todos los retornos de su promesa en suscheduleScanfunción.fuente
scheduledScanque siempre se llama después de todas las demás funciones de sincronizaciónscan. Si este es el caso, entonces sí, mi respuesta sigue siendo válida. Simplemente siempre devuelva la promesa que se devolveráscheduleScanen lascanfunciónupdatellamadasscheduledScano cualquier número de funciones entre ellos. El punto clave es que debe devolver la cadena de promesa desdescheduleScanel principio hasta lascanfunción. Entonces, siscanllama aupdatequé llamadasfinalise..... Qué llamadas ascheduleScanla cadena de promesa deberán devolverse a través de todas las invocaciones de funciones, es decir, solo asegúrese de devolver la promesa de cada una de estas funciones.La función de escaneo es una función asincrónica. En su
queue.process()función, debe esperar la función de escaneo y luego llamar a ladone()devolución de llamada.¡Prueba esto! Intenté refactorizar un poco el código usando async-await.
fuente