Baseline commit of the existing Maquina Comercial Pessoal project
Tracks the app that was already in place (capture, treatment, outreach, WhatsApp integration, server, frontend, tests, docs) so future feature work can branch and use isolated worktrees.
This commit is contained in:
@@ -0,0 +1,82 @@
|
||||
import { loadDotEnv, APP_PORT, paths } from '../src/env.mjs';
|
||||
import { openDb, ensureSeeds, recoverPendingOutreach, updateOutreachMessageStatus } from '../src/db.mjs';
|
||||
import { createJobManager, recoverOrphans } from '../src/jobs/manager.mjs';
|
||||
import { createAppServer } from '../src/server/index.mjs';
|
||||
import { startOutreachScheduler } from '../src/outreach/scheduler.mjs';
|
||||
import { pauseCampaignsAfterRestart, recoverReservedCampaignQueue } from '../src/outreach/campaign-worker.mjs';
|
||||
import { recordInboundReply } from '../src/outreach/inbound.mjs';
|
||||
import { createWhatsAppManager, hasWhatsAppSession } from '../src/whatsapp/manager.mjs';
|
||||
|
||||
// Servidor local da Maquina Comercial Pessoal.
|
||||
|
||||
await loadDotEnv();
|
||||
|
||||
const log = (message) => console.log(`[servidor] ${message}`);
|
||||
|
||||
const db = openDb();
|
||||
await ensureSeeds(db, { log });
|
||||
recoverOrphans(db, log);
|
||||
recoverPendingOutreach(db);
|
||||
pauseCampaignsAfterRestart(db);
|
||||
recoverReservedCampaignQueue(db);
|
||||
|
||||
const jobs = createJobManager({ db });
|
||||
const whatsapp = createWhatsAppManager({
|
||||
authDir: paths.whatsappAuth,
|
||||
log,
|
||||
onMessageStatus: (event) => updateOutreachMessageStatus(db, event),
|
||||
onInboundMessage: (event) => recordInboundReply(db, event)
|
||||
});
|
||||
if (await hasWhatsAppSession(paths.whatsappAuth)) {
|
||||
whatsapp.connect().catch((error) => log(`whatsapp: reconexao inicial falhou: ${error.message}`));
|
||||
}
|
||||
const server = createAppServer({ db, jobs, whatsapp, log });
|
||||
const stopScheduler = startOutreachScheduler({ db, whatsapp, log });
|
||||
|
||||
const port = APP_PORT;
|
||||
server.listen(port, '127.0.0.1', () => {
|
||||
log(`Maquina Comercial Pessoal rodando em http://127.0.0.1:${port}`);
|
||||
log('somente este computador tem acesso (127.0.0.1). Ctrl+C para encerrar.');
|
||||
});
|
||||
|
||||
let shuttingDown = false;
|
||||
async function shutdown() {
|
||||
if (shuttingDown) return;
|
||||
shuttingDown = true;
|
||||
log('encerrando...');
|
||||
const watchdog = setTimeout(() => process.exit(1), 30_000);
|
||||
watchdog.unref();
|
||||
|
||||
const shutdownTasks = [
|
||||
stopScheduler().catch((error) => log(`outreach: falha ao encerrar scheduler: ${error.message}`)),
|
||||
jobs.close().catch((error) => log(`jobs: falha ao encerrar: ${error.message}`)),
|
||||
whatsapp.close().catch((error) => log(`whatsapp: falha ao encerrar: ${error.message}`))
|
||||
];
|
||||
let resourceTimer;
|
||||
const resourcesTimedOut = await Promise.race([
|
||||
Promise.allSettled(shutdownTasks).then(() => false),
|
||||
new Promise((resolve) => {
|
||||
resourceTimer = setTimeout(() => resolve(true), 20_000);
|
||||
resourceTimer.unref();
|
||||
})
|
||||
]);
|
||||
clearTimeout(resourceTimer);
|
||||
if (resourcesTimedOut) log('encerramento dos recursos excedeu o prazo; prosseguindo');
|
||||
|
||||
recoverOrphans(db, log);
|
||||
let httpTimer;
|
||||
const httpTimedOut = await Promise.race([
|
||||
new Promise((resolve) => server.close(resolve)).then(() => false),
|
||||
new Promise((resolve) => {
|
||||
httpTimer = setTimeout(() => resolve(true), 5_000);
|
||||
httpTimer.unref();
|
||||
})
|
||||
]);
|
||||
clearTimeout(httpTimer);
|
||||
if (httpTimedOut) log('encerramento HTTP excedeu o prazo; prosseguindo');
|
||||
db.close();
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
process.on('SIGINT', shutdown);
|
||||
process.on('SIGTERM', shutdown);
|
||||
Reference in New Issue
Block a user