// reeeper/cron/expire-crashed-hosts.js // Copyright (C) 2022 DTP Technologies, LLC // License: Apache-2.0 'use strict'; const path = require('path'); const mongoose = require('mongoose'); const NetHost = mongoose.model('NetHost'); const { CronJob } = require('cron'); const { SiteWorkerProcess } = require(path.join(__dirname, '..', '..', '..', '..', 'lib', 'site-lib')); /** * Hosts on the DTP network register themselves and periodically report various * metrics. They clean up after themselves when exiting gracefully. But, hosts * lose power or get un-plugged or get caught in a sharknado or whatever. * * When that happens, the Reeeper ensures those hosts don't become Night of the * Living Dead. * * That is the formal technical explanation of what's going on in here. We're * preventing DTP host processes from becoming The Night of the Living Dead. */ class CrashedHostsCron extends SiteWorkerProcess { static get COMPONENT ( ) { return { name: 'crashedHostsCron', slug: 'crashed-hosts-cron', }; } constructor (worker) { super(worker, CrashedHostsCron.COMPONENT); } async start ( ) { await super.start(); await this.expireCrashedHosts(); // first-run the expirations this.job = new CronJob( '*/5 * * * * *', this.expireCrashedHosts.bind(this), null, true, process.env.DTP_CRON_TIMEZONE || 'America/New_York', ); } async stop ( ) { if (this.job) { this.log.info('stopping host expire job'); this.job.stop(); delete this.job; } await super.stop(); } async expireCrashedHosts ( ) { try { await NetHost .find({ status: 'crashed' }) .select('_id hostname') .lean() .cursor() .eachAsync(async (host) => { this.log.info('deactivating crashed host', { hostname: host.hostname }); await NetHost.updateOne({ _id: host._id }, { $set: { status: 'inactive' } }); }); } catch (error) { this.log.error('failed to expire crashed hosts', { error }); } } } module.exports = CrashedHostsCron;