Sidequest.js: uma alternativa simples e robusta para jobs distribuídos no Node.js
Olá pessoal, tudo beleza?
Há alguns anos, criei uma lib para trabalhar com agendamento de tarefas no Node.js. O node-cron até que é uma lib relativamente utilizada pela comunidade, com mais de 5 milhões de downloads por semana. A ideia na época era criar algo simples, sem dependências externas, para evitar o uso direto de setInterval.
Porém, com o passar dos anos, percebi que a lib começou a ser usada de formas que não eram o objetivo inicial. Basicamente, começaram a adicioná-la em web apps, como APIs com Express, e a executar jobs recorrentes no mesmo processo do Express.
Com isso, identifiquei dois grandes problemas:
- Tasks recorrentes com blocking I/O fazem a API com Express parar de responder, se tudo estiver rodando no mesmo processo.
- Se o app for deployado em vários nós, existirão N tasks recorrentes sendo executadas simultaneamente. Ou seja, os jobs são executados em duplicidade.
Pensando nisso, e inspirado pelo Oban (Elixir) e Sidekiq (Rails), criei o Sidequest.js.
A ideia é ter algo simples de usar, que possa aproveitar o que o app já tem, como PostgreSQL, MySQL ou MongoDB, e que resolva esses problemas de jobs distribuídos. Até existe uma solução similar, o BullMQ, porém ela roda apenas com Redis.
A utilização é basicamente:
1 - Criar um Job:
import { Job } from "sidequest";
export class EmailJob extends Job {
async run(to, subject, body) {
console.log(`Sending email to ${to}: ${subject}`);
// Your email sending logic here
return { sent: true, timestamp: new Date() };
}
}
2 - Iniciar o Sidequest.js junto com a aplicação:
await Sidequest.start({
backend: {
driver: "@sidequest/postgres-backend",
config: "postgresql://postgres:postgres@localhost:5432/my_app_dev",
}
});
Neste exemplo, está usando o PostgreSQL como backend.
3 - Fazer o enqueue do job:
await Sidequest.build(EmailJob).enqueue("[email protected]", "Welcome!", "Thanks for signing up!");
Isso pode ser feito de qualquer lugar, como em um handler de rota no Express.
Pontos importantes: o Sidequest roda em um fork process e todos os jobs são executados em worker threads. Ou seja, ele roda totalmente isolado do processo principal.
Além disso, implementa algumas features interessantes, como jobs únicos, retry com backoff exponencial, snooze, entre outros.
Ah, e também há um dashboard que pode ser usado para acompanhar os jobs:
https://sidequestjs.com/screenshot.png
O Sidequest.js acabou de ser liberado. Seria muito massa se vocês puderem experimentar, testar e me contar o que acharam. Qualquer feedback, sugestão ou bug encontrado é super bem-vindo. Espero que seja útil no dia a dia de quem trabalha com Node.js e precisa de uma solução simples e robusta para tarefas em background.