/*********************************************************************************************************************************************************************** * File Name : client.cron.js * Type : Cron Registry — Client side * Description : Aggregates and registers every client-facing scheduled job. * Same shape as admin.cron.js — each job module exports * { name, schedule, run }, listed in the `jobs` array below. * * The settings-backed jobs emit notifications, so their * schedule/enabled state lives in cron_notification_settings * and is configurable from /admin/notifications/settings * without a restart. expireAdvertisements has no notification * tied to it, so it stays on a plain hardcoded schedule (same * reasoning as liftExpiredBans in admin.cron.js). * * Currently registered: * - userNotifications (cron/jobs/user_notifications.cron.js) * - issueCertificates (cron/jobs/issue_certificates.cron.js) * - expireUserTiers (cron/jobs/expire_user_tiers.cron.js) * - taskDueSoon (cron/jobs/task_due_soon.cron.js) * - expireAdvertisements (cron/jobs/expire_advertisements.cron.js) — plain * - failStalePayments (cron/jobs/fail_stale_payments.cron.js) — plain * * Author: Kenneth Obsequio (@lash0000) * Date Created: Jun. 17, 2026 ***********************************************************************************************************************************************************************/ const cron = require('node-cron'); const userNotifications = require('./jobs/user_notifications.cron'); const issueCertificates = require('./jobs/issue_certificates.cron'); const expireUserTiers = require('./jobs/expire_user_tiers.cron'); const taskDueSoon = require('./jobs/task_due_soon.cron'); const expireAdvertisements = require('./jobs/expire_advertisements.cron'); const failStalePayments = require('./jobs/fail_stale_payments.cron'); const { startSettingsBackedJobs } = require('./cronRegistry.util'); // ─── Registry — add future client-side cron jobs here ──────────────────────── const settingsBackedJobs = [ userNotifications, issueCertificates, expireUserTiers, taskDueSoon, ]; // Plain hardcoded-schedule jobs (not tied to any notification setting). const plainJobs = [ expireAdvertisements, failStalePayments, ]; // ─── Boot all registered client-side jobs ───────────────────────────────────── async function startClientCronJobs() { const registered = await startSettingsBackedJobs(settingsBackedJobs, 'CLIENT'); for (const job of plainJobs) { if (!cron.validate(job.schedule)) { console.error(`[CRON][CLIENT] Invalid schedule for "${job.name}": "${job.schedule}" — skipped.`); continue; } cron.schedule(job.schedule, job.run); registered.push({ name: job.name, scope: 'CLIENT', schedule: job.schedule }); } return registered; } module.exports = { startClientCronJobs };