vê se a responsta do chatgpt te ajuda:
Para lidar com a inserção de um grande número de contatos no banco de dados sem interferir no restante das operações, você pode usar uma abordagem assíncrona e/ou paralela para inserir os contatos em lotes. Aqui está um exemplo de como você pode fazer isso no Adonis.JS usando async/await e Promise.all:
const upsert: BaileysEventHandler<'contacts.upsert'> = async (contacts: BaileysContact[]) => {
try {
// Dividir os contatos em lotes para inserção
const batchSize = 100; // Número de contatos em cada lote
const batches = [];
for (let i = 0; i < contacts.length; i += batchSize) {
batches.push(contacts.slice(i, i + batchSize));
}
// Executar a inserção em lotes em paralelo
await Promise.all(batches.map(async (batch) => {
const trx = await Database.transaction();
const transformedContacts = await Promise.all(batch.map(async (data) => {
return transformDataOnStore(data);
}));
const wppIds = transformedContacts.map((contact) => contact.wpp_id);
const images = await contactService.getMultipleImages(wppIds, client);
if (images?.length) {
transformedContacts.forEach((contact, index) => {
const matchedImage = images.find((img) => img.wpp_id === contact.wpp_id);
transformedContacts[index]['img_url'] = matchedImage?.image ?? null;
});
}
await Contact.updateOrCreateMany('wpp_id', transformedContacts, trx);
await trx.commit();
}));
} catch (error) {
Logger.error(error, 'Ocorreu um erro ao criar/atualizar contatos');
}
};
Neste código, os contatos são divididos em lotes de tamanho batchSize
e cada lote é inserido em uma transação separada. Isso permite que as inserções ocorram em paralelo, melhorando a eficiência e reduzindo o tempo total de processamento. Certifique-se de ajustar o tamanho do lote conforme necessário com base na capacidade do seu banco de dados e nos requisitos de desempenho.
E também tem isso aqui
Aqui estão cinco formas de lidar com o caso de inserir muitas linhas no banco de dados em Node.js, considerando a necessidade de inserir os contatos em background sem interferir no restante das iterações:
-
Utilizando Filas de Tarefas (ex: Bull):
- Crie uma fila de tarefas utilizando uma biblioteca como Bull.
- Adicione os contatos à fila para serem processados em background.
- Implemente um worker que irá processar os contatos da fila e inseri-los no banco de dados.
- Isso permite que a inserção seja feita de forma assíncrona e em background, sem interferir nas outras operações.
-
Utilizando Promessas e Assincronia:
- Envie a inserção dos contatos para uma função assíncrona que será executada em segundo plano.
- Isso pode ser feito utilizando
setTimeout
com um tempo curto para garantir que a função seja executada em background.
-
Dividindo em Lotes (Batching):
- Divida os contatos em lotes menores e insira cada lote separadamente.
- Isso evita sobrecarregar o banco de dados com um grande número de inserções de uma vez.
- Utilize uma estratégia de controle de taxa para garantir que os lotes sejam inseridos de forma eficiente.
-
Utilizando Threads de Trabalho (Worker Threads):
- Utilize threads de trabalho para realizar a inserção dos contatos em paralelo.
- Isso permite que a inserção seja feita de forma concorrente, aproveitando melhor os recursos do sistema.
-
Utilizando Processos Secundários (Child Processes):
- Crie processos secundários para lidar com a inserção dos contatos.
- Isso permite que a inserção seja feita em um processo separado, deixando o processo principal livre para outras operações.
Escolha a abordagem que melhor se adapta às necessidades do seu projeto e à infraestrutura disponível.
Acabei vendo que no adonis tem algo pré pronto (Knex) pra fazer inserções particionadas, que seria o batchInsert. Ficou ligeiramente mais eficaz, porém não sei se atingi a melhor prática ainda, sabendo que é um SaaS, então serão muitas empresas salvando os contatos (embora seja apenas uma vez ao ler o QRCode).
Agradeço a ajuda <3