This commit is contained in:
MDeeApp
2025-10-11 01:17:31 +02:00
commit 8eb060f380
1223 changed files with 265299 additions and 0 deletions

85
src/scheduler.ts Normal file
View 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();