// reeeper/cron/expire-announcements.js // Copyright (C) 2022 DTP Technologies, LLC // License: Apache-2.0 'use strict'; const path = require('path'); const moment = require('moment'); const mongoose = require('mongoose'); const Announcement = mongoose.model('Announcement'); const { CronJob } = require('cron'); const { SiteWorkerProcess } = require(path.join(__dirname, '..', '..', '..', '..', 'lib', 'site-lib')); /** * Announcements used to auto-expire from the MongoDB database after 21 days, * but then I added commenting. Now, an auto-expiring Announcement would orphan * all those comments. That's bad. * * The solution, therefore, is to have a cron that wakes up daily and expires * all Announcements older than 21 days. Same policy, it just also cleans up * the comments and whatever else gets bolted onto an Announcement over time. * * This is how you do that. */ class ExpiredAnnouncementsCron extends SiteWorkerProcess { static get COMPONENT ( ) { return { logId: 'expired-announcements-cron', index: 'expiredAnnouncementsCron', className: 'ExpiredAnnouncementsCron', }; } constructor (worker) { super(worker, ExpiredAnnouncementsCron.COMPONENT); } async start ( ) { await super.start(); this.log.info('performing startup expiration of announcements'); await this.expireAnnouncements(); this.log.info('starting daily cron to expire announcements'); this.job = new CronJob( '0 0 0 * * *', // at midnight every day this.expireAnnouncements.bind(this), null, true, process.env.DTP_CRON_TIMEZONE || 'America/New_York', ); } async stop ( ) { if (this.job) { this.log.info('stopping announcement expire job'); this.job.stop(); delete this.job; } await super.stop(); } async expireAnnouncements ( ) { const { announcement: announcementService } = this.dtp.services; const NOW = new Date(); const OLDEST_DATE = moment(NOW).subtract(21, 'days').toDate(); try { await Announcement .find({ created: { $lt: OLDEST_DATE } }) .lean() .cursor() .eachAsync(async (announcement) => { try { await announcementService.remove(announcement); } catch (error) { this.log.error('failed to remove expired Announcement', { announcementId: announcement._id, error, }); // fall through, we'll get it in a future run } }); } catch (error) { this.log.error('failed to expire crashed hosts', { error }); } } } module.exports = ExpiredAnnouncementsCron;