email-amazon/email-worker-nodejs/main.ts

90 lines
3.1 KiB
TypeScript

/**
* Main entry point for unified email worker
*
* Startup sequence:
* 1. Load configuration and domains
* 2. Start Prometheus metrics server
* 3. Start health check server
* 4. Initialize UnifiedWorker
* 5. Register signal handlers for graceful shutdown
*/
import { config, loadDomains } from './config.js';
import { log } from './logger.js';
import { startMetricsServer, type MetricsCollector } from './metrics.js';
import { startHealthServer } from './health.js';
import { UnifiedWorker } from './worker/index.js';
// ---------------------------------------------------------------------------
// Banner
// ---------------------------------------------------------------------------
function printBanner(domains: string[]): void {
log('╔══════════════════════════════════════════════════╗');
log('║ Unified Email Worker (TypeScript) ║');
log('║ Version 2.0.0 ║');
log('╚══════════════════════════════════════════════════╝');
log('');
log(`Domains (${domains.length}):`);
for (const d of domains) {
log(`${d}`);
}
log('');
log(`SMTP: ${config.smtpHost}:${config.smtpPort}`);
log(`Internal SMTP: port ${config.internalSmtpPort}`);
log(`Poll interval: ${config.pollInterval}s`);
log(`Metrics: port ${config.metricsPort}`);
log(`Health: port ${config.healthPort}`);
log('');
}
// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------
async function main(): Promise<void> {
// 1. Load domains
const domains = loadDomains();
if (domains.length === 0) {
log('❌ No domains configured. Set DOMAINS env var or provide DOMAINS_FILE.', 'ERROR');
process.exit(1);
}
printBanner(domains);
// 2. Metrics server
const metrics: MetricsCollector | null = await startMetricsServer(config.metricsPort);
// 3. Unified worker
const worker = new UnifiedWorker(domains, metrics);
// 4. Health server
startHealthServer(config.healthPort, domains, () => worker.getStats());
// 5. Signal handlers
let shuttingDown = false;
const shutdown = async (signal: string) => {
if (shuttingDown) return;
shuttingDown = true;
log(`\n🛑 Received ${signal}. Shutting down gracefully...`);
await worker.stop();
log('👋 Goodbye.');
process.exit(0);
};
process.on('SIGINT', () => shutdown('SIGINT'));
process.on('SIGTERM', () => shutdown('SIGTERM'));
// 6. Start
await worker.start();
// Keep alive (event loop stays open due to HTTP servers + SQS polling)
log('✅ Worker is running. Press Ctrl+C to stop.');
}
// ---------------------------------------------------------------------------
main().catch((err) => {
log(`💥 Fatal startup error: ${err.message ?? err}`, 'CRITICAL');
log(err.stack ?? '', 'CRITICAL');
process.exit(1);
});