Mam dwie funkcje scheduleScan()
i scan()
.
scan()
dzwoni, scheduleScan()
gdy nie pozostaje nic innego, jak zaplanować nowy skan , więc scheduleScan()
można zaplanować scan()
. Ale jest problem, niektóre zadania uruchamiane są dwukrotnie.
Chcę mieć pewność, że w danym momencie przetwarzane jest tylko jedno zadanie. Jak mogę to osiągnąć? Wydaje mi się, że ma to coś wspólnego done()
(został usunięty ze skanu (), teraz usunięty), ale nie mogłem znaleźć rozwiązania.
Wersja byka: 3.12.1
Ważna późna edycja: scan()
wywołuje inne funkcje i mogą, ale nie muszą, wywoływać inne funkcje, ale wszystkie one są funkcjami synchronizacji, więc wywołują funkcję tylko po zakończeniu ich własnych zadań, jest tylko jedna droga do przodu. Na końcu „drzewa” nazywam to, ostatnia funkcja wywołuje harmonogramScan (), ale nie mogą być uruchomione dwa jednoczesne zadania. Nawiasem scan()
mówiąc, każda praca zaczyna się o, a kończy nascheduleScan(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)
})
}
})
}
źródło
scan
funkcji, czy możesz pomóc?Odpowiedzi:
Problem, jak sądzę, polega na tym, że twoja
scan
funkcja jest asynchroniczna. Twojajob.progress
funkcja wywołuje,scan
a następnie natychmiast wywołuje,done
umożliwiając kolejce przetworzenie innego zadania.Rozwiązaniem może być zdać
done
zwrotnego jako parametr do swoichscan
andscheduleScan
funkcji i wywołać ją, po zakończeniu swojej pracy (lub w przypadku błędu).Innym (lepszym) rozwiązaniem może być zapewnienie, że zawsze zwrócisz
Promise
odscan
ischeduleScan
, a następnie zaczekasz na obietnicę do rozwiązania, a następnie zadzwoniszdone
. Jeśli to zrobisz, upewnij się, że w łańcuchu masz wszystkie zwroty obietnicscheduleScan
.źródło
scheduledScan
jest zawsze wywoływany po wszystkich innych funkcjach synchronizacjiscan
. Jeśli tak, to tak, moja odpowiedź jest nadal aktualna. Po prostu zawsze zwracaj obietnicę, która zostanie zwróconascheduleScan
wscan
funkcjiupdate
połączeniascheduledScan
lub dowolna liczba funkcji między nimi. Kluczową kwestią jest to, że musisz przywrócić łańcuch obietnic zscheduleScan
powrotem doscan
funkcji. Więc jeśliscan
wywołania,update
które wywołająfinalise
..... Które wywołaniascheduleScan
łańcuch obietnicy będzie musiał zostać zwrócony przez wszystkie wywołania funkcji, tj. Upewnij się, że zwróciłeś obietnicę z każdej z tych funkcji.Funkcja skanowania jest funkcją asynchroniczną. W swojej
queue.process()
funkcji musisz poczekać na funkcję skanowania, a następniedone()
oddzwonić.Spróbuj tego! Próbowałem trochę przebudować kod, używając asynchronicznego oczekiwania.
źródło