Browse Source
- 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"pull/2/head
16 changed files with 155 additions and 48 deletions
@ -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