67 lines
2.1 KiB
TypeScript
67 lines
2.1 KiB
TypeScript
import 'dotenv/config';
|
|
import { Pool } from 'pg';
|
|
import { scrapeAll } from './scraper';
|
|
import { syncToDatabase } from './db';
|
|
|
|
function log(msg: string) {
|
|
console.log(`[sync] ${new Date().toISOString()} ${msg}`);
|
|
}
|
|
|
|
function requireEnv(name: string): string {
|
|
const val = process.env[name];
|
|
if (!val) throw new Error(`Missing required environment variable: ${name}`);
|
|
return val;
|
|
}
|
|
|
|
/** Returns milliseconds until the next midnight (00:00:00) in local time. */
|
|
function msUntilMidnight(): number {
|
|
const now = new Date();
|
|
const midnight = new Date(now);
|
|
midnight.setDate(now.getDate() + 1);
|
|
midnight.setHours(0, 0, 0, 0);
|
|
return midnight.getTime() - now.getTime();
|
|
}
|
|
|
|
async function runSync(): Promise<void> {
|
|
const username = requireEnv('FDISK_USERNAME');
|
|
const password = requireEnv('FDISK_PASSWORD');
|
|
|
|
const pool = new Pool({
|
|
host: requireEnv('DB_HOST'),
|
|
port: parseInt(process.env.DB_PORT ?? '5432'),
|
|
database: requireEnv('DB_NAME'),
|
|
user: requireEnv('DB_USER'),
|
|
password: requireEnv('DB_PASSWORD'),
|
|
});
|
|
|
|
try {
|
|
log('Starting FDISK sync');
|
|
const { members, ausbildungen } = await scrapeAll(username, password);
|
|
await syncToDatabase(pool, members, ausbildungen);
|
|
log(`Sync complete — ${members.length} members, ${ausbildungen.length} Ausbildungen`);
|
|
} finally {
|
|
await pool.end();
|
|
}
|
|
}
|
|
|
|
async function main(): Promise<void> {
|
|
log('FDISK sync service started');
|
|
|
|
// Run once immediately on startup so the first sync doesn't wait until midnight
|
|
await runSync().catch(err => log(`ERROR during initial sync: ${err.message}`));
|
|
|
|
// Then schedule at midnight every day
|
|
while (true) {
|
|
const delay = msUntilMidnight();
|
|
const nextRun = new Date(Date.now() + delay);
|
|
log(`Next sync scheduled at ${nextRun.toLocaleString()} (in ${Math.round(delay / 60000)} min)`);
|
|
await new Promise(r => setTimeout(r, delay));
|
|
await runSync().catch(err => log(`ERROR during scheduled sync: ${err.message}`));
|
|
}
|
|
}
|
|
|
|
main().catch(err => {
|
|
console.error(`[sync] Fatal error: ${err.message}`);
|
|
process.exit(1);
|
|
});
|