import config from "config"; import moment from "moment-timezone"; import { ILogObj, Logger } from "tslog"; import cron from "node-cron"; import { OrmHelper } from "./helpers/orm"; import { CrawlingService } from "./services/crawling"; // Set timezone moment.tz.setDefault("Asia/Jakarta"); const log: Logger = new Logger({ name: "[CrawlerIndex]", type: "pretty", }); log.settings.prettyLogTimeZone = "local"; let isCrawlingRunning = false; /** * Start the crawling service */ async function startCrawlingService() { try { // Initialize database connection log.info("Initializing database connection..."); await OrmHelper.setup(); // Wait a bit for database to be ready await new Promise((resolve) => setTimeout(resolve, 2000)); // Verify database is initialized if (!OrmHelper.DB || !OrmHelper.DB.isInitialized) { throw new Error("Database not initialized"); } log.info("Database connection established"); // Start cron job const cronInterval = config.get("crawler.interval"); log.info(`Starting crawling service with interval: ${cronInterval}`); const crawlingJob = cron.schedule(cronInterval, async () => { if (isCrawlingRunning) { log.warn("Crawling service is still running. Skipping this schedule."); return; } log.info(`Running crawling service at: ${new Date().toLocaleString()}`); isCrawlingRunning = true; try { await CrawlingService.runCrawling(); log.info(`Crawling service completed at: ${new Date().toLocaleString()}`); } catch (error) { log.error("Crawling service failed:", error); } finally { isCrawlingRunning = false; } }); log.info( `Crawling service started. App: ${config.get("app.name")} v${config.get("app.version")}` ); log.info(`Environment: ${config.get("app.env")}`); log.info(`Cron schedule: ${cronInterval}`); // Run immediately on startup (optional) // Uncomment the line below if you want to run crawling immediately on startup // await CrawlingService.runCrawling(); } catch (error) { log.error("Failed to start crawling service:", error); process.exit(1); } } // Handle graceful shutdown const onCloseSignal = () => { log.info("SIGINT/SIGTERM received, shutting down gracefully"); if (OrmHelper.DB && OrmHelper.DB.isInitialized) { OrmHelper.DB.destroy() .then(() => { log.info("Database connection closed"); process.exit(0); }) .catch((error) => { log.error("Error closing database connection:", error); process.exit(1); }); } else { process.exit(0); } }; process.on("SIGINT", onCloseSignal); process.on("SIGTERM", onCloseSignal); // Handle uncaught errors process.on("unhandledRejection", (reason, promise) => { log.error("Unhandled Rejection at:", promise, "reason:", reason); }); process.on("uncaughtException", (error) => { log.error("Uncaught Exception:", error); process.exit(1); }); // Start the service startCrawlingService();