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