initial
This commit is contained in:
85
src/scheduler.ts
Normal file
85
src/scheduler.ts
Normal file
@@ -0,0 +1,85 @@
|
||||
import { config } from "./config.js";
|
||||
import { listUpcomingDeadlines } from "./contractsStore.js";
|
||||
import { createLogger } from "./logger.js";
|
||||
import { sendDeadlineNotifications } from "./notifications.js";
|
||||
import { getRuntimeSettings } from "./runtimeSettings.js";
|
||||
|
||||
const logger = createLogger(config.logLevel);
|
||||
|
||||
export class DeadlineMonitor {
|
||||
private timer: NodeJS.Timeout | null = null;
|
||||
private running = false;
|
||||
|
||||
start() {
|
||||
if (this.running) {
|
||||
return;
|
||||
}
|
||||
this.running = true;
|
||||
const settings = getRuntimeSettings();
|
||||
logger.info(
|
||||
`Starting deadline monitor (interval=${settings.schedulerIntervalMinutes} min, alert window=${settings.alertDaysBefore} days)`
|
||||
);
|
||||
this.scheduleNext(1000);
|
||||
}
|
||||
|
||||
stop() {
|
||||
if (!this.running) {
|
||||
return;
|
||||
}
|
||||
this.running = false;
|
||||
if (this.timer) {
|
||||
clearTimeout(this.timer);
|
||||
this.timer = null;
|
||||
}
|
||||
logger.info("Deadline monitor stopped.");
|
||||
}
|
||||
|
||||
private scheduleNext(delayMs?: number) {
|
||||
if (!this.running) {
|
||||
return;
|
||||
}
|
||||
const settings = getRuntimeSettings();
|
||||
const intervalMs = Math.max(settings.schedulerIntervalMinutes, 5) * 60 * 1000;
|
||||
const wait = delayMs ?? intervalMs;
|
||||
|
||||
this.timer = setTimeout(() => {
|
||||
this.runCheck()
|
||||
.catch((error) => {
|
||||
logger.error("Deadline check failed", error);
|
||||
})
|
||||
.finally(() => {
|
||||
this.scheduleNext();
|
||||
});
|
||||
}, wait);
|
||||
}
|
||||
|
||||
private async runCheck() {
|
||||
const settings = getRuntimeSettings();
|
||||
const deadlines = listUpcomingDeadlines(settings.alertDaysBefore);
|
||||
|
||||
if (deadlines.length === 0) {
|
||||
logger.debug("No upcoming deadlines within alert window.");
|
||||
return;
|
||||
}
|
||||
|
||||
const lines = deadlines.map(
|
||||
(item) =>
|
||||
`${item.title} (#${item.id}) — cancel by ${item.terminationDeadline} (${item.daysUntilDeadline} days left)`
|
||||
);
|
||||
|
||||
for (const item of deadlines) {
|
||||
logger.warn(
|
||||
"Upcoming deadline: %s (provider=%s, documentId=%s, terminate by %s, days=%s)",
|
||||
item.title,
|
||||
item.provider ?? "n/a",
|
||||
item.paperlessDocumentId ?? "n/a",
|
||||
item.terminationDeadline ?? "n/a",
|
||||
item.daysUntilDeadline ?? "n/a"
|
||||
);
|
||||
}
|
||||
|
||||
await sendDeadlineNotifications("Contract termination reminder", lines, settings);
|
||||
}
|
||||
}
|
||||
|
||||
export const deadlineMonitor = new DeadlineMonitor();
|
||||
Reference in New Issue
Block a user