- Moved the responsibility of expiring Announcements from MongoDB into the Reeeper - Added logic to clean up comments attached to an expiring Announcement - ResourceStats are now much more universal and common - CommentStats are for comments only - More routines to comment on and vote on "content resources"master
parent
5e90fca353
commit
91fe2ab01b
@ -0,0 +1,94 @@
|
|||||||
|
// 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 {
|
||||||
|
name: 'expiredAnnouncementsCron',
|
||||||
|
slug: 'expired-announcements-cron',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
Loading…
Reference in new issue