2026-08-31 18:51:27 +00:00
|
|
|
import {
|
|
|
|
|
AsyncLocalStorageOperationContextStore,
|
|
|
|
|
AuditChangeModel,
|
|
|
|
|
AuditEventModel,
|
|
|
|
|
OperationAuditContextProvider,
|
|
|
|
|
SequelizeAuditStore,
|
|
|
|
|
SequelizeTransactionContext,
|
|
|
|
|
auditModelInitializers,
|
|
|
|
|
closeSequelize,
|
|
|
|
|
createSequelize,
|
|
|
|
|
initModules,
|
|
|
|
|
registerModels,
|
|
|
|
|
} from "@erp/core/api";
|
|
|
|
|
import { Audit } from "@repo/rdx-audit";
|
|
|
|
|
import { configureLogger, setLoggerSingleton } from "@repo/rdx-logger";
|
|
|
|
|
|
|
|
|
|
import { loadWorkerConfig } from "./config/worker-config";
|
|
|
|
|
import { registerWorkerModules } from "./modules/register-modules";
|
|
|
|
|
import { registerJobs } from "./scheduler/register-jobs";
|
2026-09-10 11:26:33 +00:00
|
|
|
import { Scheduler } from "./scheduler/scheduler";
|
2026-08-31 18:51:27 +00:00
|
|
|
|
|
|
|
|
const logger = configureLogger("console", { service: "worker" });
|
|
|
|
|
setLoggerSingleton(logger);
|
|
|
|
|
const config = loadWorkerConfig(logger);
|
|
|
|
|
const operationContext = new AsyncLocalStorageOperationContextStore();
|
|
|
|
|
const transactionContext = new SequelizeTransactionContext();
|
|
|
|
|
let stopping: Promise<void> | null = null;
|
|
|
|
|
|
|
|
|
|
async function bootstrap(): Promise<void> {
|
|
|
|
|
logger.info("Worker starting");
|
|
|
|
|
const database = await createSequelize(config.database, logger);
|
2026-09-10 11:26:33 +00:00
|
|
|
const audit = new Audit({
|
|
|
|
|
source: { type: "application", id: "factuges-worker" },
|
|
|
|
|
contextProvider: new OperationAuditContextProvider(operationContext),
|
|
|
|
|
store: new SequelizeAuditStore(AuditEventModel, AuditChangeModel, transactionContext),
|
|
|
|
|
});
|
2026-08-31 18:51:27 +00:00
|
|
|
registerWorkerModules();
|
|
|
|
|
registerModels(auditModelInitializers, "worker-infrastructure");
|
2026-09-10 11:26:33 +00:00
|
|
|
const modulesRuntime = await initModules({
|
|
|
|
|
config,
|
|
|
|
|
database,
|
|
|
|
|
logger,
|
|
|
|
|
operationContext,
|
|
|
|
|
transactionContext,
|
|
|
|
|
audit,
|
|
|
|
|
warmup: { timeoutMs: 10_000, strict: false },
|
|
|
|
|
databaseSyncMode: "none",
|
|
|
|
|
getService: () => {
|
|
|
|
|
throw new Error("Services are available only in module scope.");
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
const scheduler = new Scheduler(
|
|
|
|
|
registerJobs({ config, logger, runtime: modulesRuntime }),
|
|
|
|
|
logger
|
|
|
|
|
);
|
2026-08-31 18:51:27 +00:00
|
|
|
scheduler.start();
|
|
|
|
|
logger.info("Worker started");
|
2026-09-10 11:26:33 +00:00
|
|
|
const shutdown = async () => {
|
|
|
|
|
if (stopping) {
|
|
|
|
|
return stopping;
|
|
|
|
|
}
|
|
|
|
|
stopping = (async () => {
|
|
|
|
|
logger.info("Worker stopping");
|
|
|
|
|
await scheduler.stop();
|
|
|
|
|
await closeSequelize(database, logger);
|
|
|
|
|
logger.info("Worker stopped");
|
|
|
|
|
})();
|
|
|
|
|
return stopping;
|
|
|
|
|
};
|
|
|
|
|
process.on("SIGINT", () => {
|
|
|
|
|
shutdown()
|
|
|
|
|
.then(() => process.exit(0))
|
|
|
|
|
.catch(() => process.exit(1));
|
|
|
|
|
});
|
|
|
|
|
process.on("SIGTERM", () => {
|
|
|
|
|
shutdown()
|
|
|
|
|
.then(() => process.exit(0))
|
|
|
|
|
.catch(() => process.exit(1));
|
|
|
|
|
});
|
2026-08-31 18:51:27 +00:00
|
|
|
}
|
|
|
|
|
|
2026-09-10 11:26:33 +00:00
|
|
|
bootstrap().catch((error) => {
|
|
|
|
|
logger.error("Worker bootstrap failed", { error });
|
|
|
|
|
process.exit(1);
|
|
|
|
|
});
|