Em ambientes multi-tenant de alta escala, gerenciar dezenas de tarefas em segundo plano heterogêneas — abrangendo auditorias automatizadas de qualidade (QA), descoberta de leads comerciais, roteamento de e-mails transacionais via OAuth e sincronização distribuída de conteúdo — torna-se rapidamente insustentável quando executado por meio de agendamentos cron desacoplados ou scripts avulsos. Sem um framework centralizado de orquestração, processos de longa duração correm o risco de gerar processos órfãos (zombie/orphan processes), saturar os núcleos de CPU do servidor e operar sem observabilidade em tempo real.

Para resolver esse desafio arquitetural, projetamos o Job Runner v2.0: uma plataforma de automação corporativa de alta vazão em Node.js e TypeScript, construída sobre uma arquitetura modular de plugins. Ao definir contratos declarativos estritamente tipados, o Job Runner consolidou três motores legados independentes — QA Watchdog, Lead Hunter e Article Sync — em uma única plataforma isolada por grupos de processos e instrumentada ponta a ponta.

1. O Problema dos Scripts de Segundo Plano Fragmentados

Antes da consolidação em um executor unificado no nó dedicado de processamento (192.168.11.18:8084), cada ferramenta operacional funcionava em seu próprio silo isolado:

  • QA Watchdog: Disparava spiders autônomos em Playwright headless para auditar links quebrados (HTTP 404), verificar a disponibilidade de formulários de contato dinâmicos e validar esquemas estruturados JSON-LD em mais de 130 domínios em produção.
  • Lead Hunter: Executava ciclos de descoberta comercial em múltiplas etapas sobre registros empresariais regionais, enviava auditorias técnicas via API do Google Gmail e sincronizava oportunidades com o Frappe CRM.
  • Article Sync e Indexação SEO: Executava rotinas agendadas de exportação e importação para sincronizar shards JSON em disco com o MongoDB Atlas e notificar os gateways da API IndexNow.

Quando disparados via sessões SSH destacadas (nohup) ou crons tradicionais do sistema operacional, rejeições de Promises não tratadas ou loops infinitos em parsers DOM podiam travar os núcleos de CPU em 100% indefinidamente, especialmente quando instâncias órfãs do Chromium permaneciam alocadas em memória RAM.

2. A Arquitetura Modular de Plugins em TypeScript

O Job Runner v2.0 soluciona essa fragilidade abstraindo cada domínio operacional em um módulo estritamente tipado dentro de src/modules/. Cada subsistema registra suas filas e tarefas por meio de uma interface declarativa única:

export interface JobDef {
  key: string;
  name: string;
  description: string;
  queue: 'qa' | 'lead-hunter' | 'seo' | 'maintenance' | 'social';
  bin: 'node' | 'bash';
  script: string;
  cwd: string;
  baseArgs: string[];
  schedule?: string;
  retries: number;
  logFile: string;
}

A. Subsistema QA-Watchdog (src/modules/qa/)

Todas as suítes de verificação automatizada foram migradas como spiders TypeScript nativos:

  • Spider Rápido 404 (qa:spider): Percorre concorrentemente todos os domínios locatários via HTTPS, validando códigos de status HTTP e seguindo redirecionamentos 301 até o DOM final.
  • Verificação de Formulários (qa:contact-forms): Inspeciona árvores DOM renderizadas para validar formulários públicos de contato e proteção anti-abuso.
  • Auditor de Ativos Estáticos (qa:asset-audit): Verifica pacotes CSS, bundles JavaScript e imagens locais para garantir integridade visual absoluta.
  • Validador de Schema SEO (qa:seo-audit): Audita mais de 3.400 artigos publicados quanto à conformidade com Schema.org JSON-LD e metadados Open Graph.

B. Subsistema Lead-Hunter (src/modules/marketing/)

O motor de prospecção comercial foi refatorado em uma cascata determinística de cinco estágios: descoberta regional de PMEs, auditoria automatizada de falhas técnicas (ausência de SSL, LCP lento, viewport ausente), deduplicação via API REST no Frappe CRM v15, despacho exclusivo via microserviço OAuth2 do Google Gmail na porta 8085 e rastreamento automático de bounces.

C. Subsistema Article Sync e Motor de Conteúdo Versionado (src/modules/content/)

A sincronização editorial opera com escrita dupla atômica (dual-write) entre shards JSON versionados no Git, banco SQLite de revisões (data/revisions.db) e coleções do MongoDB, disparando pings instantâneos para o protocolo IndexNow a cada publicação aprovada pelo gate de qualidade.

3. Isolamento Rígido de Processos POSIX e Telemetria Grafana/Loki

Para impedir saturação de CPU e processos zumbis, o Job Runner aplica dois invariantes críticos de estabilidade operacional:

  • Sandboxing por Grupo de Processos (-pid): Cada job é iniciado com detached: true em seu próprio grupo de processos POSIX. Quando uma tarefa é interrompida ou atinge timeout, o orquestrador envia SIGTERM / SIGKILL para o ID negativo do grupo de processos (process.kill(-child.pid, 'SIGTERM')), garantindo que todos os processos filhos (incluindo processos renderizadores do Chromium headless) sejam encerrados limpa e imediatamente.
  • Telemetria Dual-Push: Todos os fluxos de log (stdout/stderr) e métricas de ciclo de vida são enviados para o Prometheus e o Promtail/Loki, alimentando painéis em tempo real no Grafana e botões de acionamento direto entre os nós do cluster (.32 e .18).
Fila de Subsistema Caminho do Módulo Limite de Concorrência Mecanismo de Isolamento e Recuperação Destino Principal de Telemetria
qa src/modules/qa/ 2 spiders paralelos Kill de grupo POSIX -pid + timeout de 15 min Loki {job="qa_watchdog"} + Prometheus
lead-hunter src/modules/marketing/ 1 pipeline serial Deduplicação idempotente no Frappe CRM + retry OAuth Loki {job="lead_hunter"} + Webhook CRM
seo / maintenance src/modules/content/ 4 workers atômicos Lock de revisão SHA-256 + escrita dupla SQLite/MongoDB Loki {job="cms_sync"} + IndexNow HTTP 200

4. Conclusão

Ao unificar validação de QA, automação de marketing e sincronização de conteúdo em uma arquitetura modular de plugins em TypeScript, transformamos uma coleção de scripts frágeis em um motor corporativo resiliente, observável e preparado para escalar novos microserviços autônomos sem tempo de inatividade.