You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

95 lines
2.6 KiB

// 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;