В общем, создаётся пул из
4*N
асинхронных обработчиков очереди productUrls, каждый из которых берет из неё задачи,
shift() . Этот пул запускается для асинхронной обработки очереди.
Внутри обработчика productUrlHandler очереди productUrls по окончанию скачивания страницы, кидается в другую очередь parseUrls, из которой обработчик parseUrlHandler выполняет парсинг асинхронно, независимо от скачивания страниц с другой очереди и результат парсинга сохраняет в СУБД или куда надо.
В итоге независимо работают обе очереди, каждая из которых работает в своём темпе и выполняет строго свою работу и одна не мешает другой. При этом, время простоя будет меньше, чем при синхронной обработке и за счёт множества асинхронных функций обратного вызова Node.js они будут распределяться по ядрам процессора.
Поднимать несколько процессов не стоит - достаточно настроить нужный размер пулов обработчиков очередей,
4*M
и
4*N
. Не нужно выставлять большой размер пула в надежде, что заработает быстрее. По началу, можно взять
M=N=1
т.е. пул из 4-ёх обработчиков.
Ни библиотек, ни фреймворков не подскажу. С Puppeteer не работал, помню что некто сказал, что эта штука сильно жрёт память.