Files
cloudron-box/src/cron.js
T

303 lines
9.4 KiB
JavaScript
Raw Normal View History

'use strict';
exports = module.exports = {
2018-09-26 12:44:38 -07:00
startPostActivationJobs: startPostActivationJobs,
startPreActivationJobs: startPreActivationJobs,
2019-03-04 10:25:18 -08:00
stopJobs: stopJobs,
handleSettingsChanged: handleSettingsChanged
};
2018-10-22 11:39:42 -07:00
var appHealthMonitor = require('./apphealthmonitor.js'),
apps = require('./apps.js'),
2017-04-13 01:07:07 -07:00
appstore = require('./appstore.js'),
assert = require('assert'),
2016-04-10 19:17:44 -07:00
backups = require('./backups.js'),
2018-01-02 12:47:33 -08:00
caas = require('./caas.js'),
cloudron = require('./cloudron.js'),
2015-10-20 11:33:19 -07:00
config = require('./config.js'),
constants = require('./constants.js'),
CronJob = require('cron').CronJob,
debug = require('debug')('box:cron'),
2017-07-21 16:13:44 +02:00
digest = require('./digest.js'),
2018-01-25 14:03:42 -08:00
dyndns = require('./dyndns.js'),
2016-07-25 12:36:43 -07:00
eventlog = require('./eventlog.js'),
2015-10-14 22:34:00 -07:00
janitor = require('./janitor.js'),
2015-10-18 08:40:24 -07:00
scheduler = require('./scheduler.js'),
settings = require('./settings.js'),
2018-07-31 11:35:23 -07:00
updater = require('./updater.js'),
updateChecker = require('./updatechecker.js');
2017-11-27 12:40:13 -08:00
var gJobs = {
alive: null, // send periodic stats
appAutoUpdater: null,
boxAutoUpdater: null,
2017-11-27 12:40:13 -08:00
appUpdateChecker: null,
backup: null,
boxUpdateChecker: null,
caasHeartbeat: null,
systemChecks: null,
2017-11-27 12:40:13 -08:00
certificateRenew: null,
cleanupBackups: null,
cleanupEventlog: null,
cleanupTokens: null,
digestEmail: null,
dockerVolumeCleaner: null,
2018-11-10 00:18:56 -08:00
dynamicDns: null,
2018-10-22 11:39:42 -07:00
schedulerSync: null,
appHealthMonitor: null
2017-11-27 12:40:13 -08:00
};
2018-12-16 20:30:09 -08:00
var NOOP_CALLBACK = function (error) { if (error) debug(error); };
2016-06-02 18:47:09 -07:00
var AUDIT_SOURCE = { userId: null, username: 'cron' };
// cron format
// Seconds: 0-59
// Minutes: 0-59
// Hours: 0-23
// Day of Month: 1-31
// Months: 0-11
// Day of Week: 0-6
2018-09-26 12:44:38 -07:00
function startPreActivationJobs(callback) {
2017-11-02 10:23:34 -07:00
if (config.provider() === 'caas') {
2017-11-27 13:40:51 -08:00
// hack: send the first heartbeat only after we are running for 60 seconds
// required as we end up sending a heartbeat and then cloudron-setup reboots the server
var seconds = (new Date()).getSeconds() - 1;
2017-11-27 15:41:24 -08:00
if (seconds === -1) seconds = 59;
2017-11-27 12:40:13 -08:00
gJobs.caasHeartbeat = new CronJob({
2017-11-27 13:40:51 -08:00
cronTime: `${seconds} */1 * * * *`, // every minute
2018-01-02 12:47:33 -08:00
onTick: caas.sendHeartbeat,
2017-11-27 13:40:51 -08:00
start: true
2017-11-02 10:23:34 -07:00
});
}
2015-10-29 08:40:52 -07:00
2018-09-26 12:44:38 -07:00
callback();
}
function startPostActivationJobs(callback) {
assert.strictEqual(typeof callback, 'function');
2016-12-19 11:56:35 -08:00
var randomHourMinute = Math.floor(60*Math.random());
2017-11-27 12:40:13 -08:00
gJobs.alive = new CronJob({
cronTime: '00 ' + randomHourMinute + ' * * * *', // every hour on a random minute
2017-04-13 01:07:07 -07:00
onTick: appstore.sendAliveStatus,
2016-11-15 15:25:21 +01:00
start: true
});
2016-12-28 14:21:41 -08:00
settings.getAll(function (error, allSettings) {
if (error) return callback(error);
recreateJobs(allSettings[settings.TIME_ZONE_KEY]);
appAutoupdatePatternChanged(allSettings[settings.APP_AUTOUPDATE_PATTERN_KEY]);
boxAutoupdatePatternChanged(allSettings[settings.BOX_AUTOUPDATE_PATTERN_KEY]);
2018-01-25 14:03:42 -08:00
dynamicDnsChanged(allSettings[settings.DYNAMIC_DNS_KEY]);
2016-12-28 14:21:41 -08:00
2015-10-27 17:05:56 -07:00
callback();
2016-12-28 14:21:41 -08:00
});
}
2019-03-04 10:25:18 -08:00
function handleSettingsChanged(key, value) {
assert.strictEqual(typeof key, 'string');
2019-03-04 15:45:04 -08:00
// value is a variant
2019-03-04 10:25:18 -08:00
switch (key) {
case settings.TIME_ZONE_KEY: recreateJobs(value); break;
case settings.APP_AUTOUPDATE_PATTERN_KEY: appAutoupdatePatternChanged(value); break;
case settings.BOX_AUTOUPDATE_PATTERN_KEY: boxAutoupdatePatternChanged(value); break;
case settings.DYNAMIC_DNS_KEY: dynamicDnsChanged(value); break;
default: break;
}
}
2016-12-28 14:21:41 -08:00
function recreateJobs(tz) {
assert.strictEqual(typeof tz, 'string');
2016-12-28 14:21:41 -08:00
debug('Creating jobs with timezone %s', tz);
2017-11-27 12:40:13 -08:00
if (gJobs.backup) gJobs.backup.stop();
gJobs.backup = new CronJob({
2018-09-04 10:48:54 -07:00
cronTime: '00 00 */6 * * *', // check every 6 hours
2016-12-28 14:21:41 -08:00
onTick: backups.ensureBackup.bind(null, AUDIT_SOURCE, NOOP_CALLBACK),
start: true,
timeZone: tz
});
2015-11-03 16:11:24 -08:00
if (gJobs.systemChecks) gJobs.systemChecks.stop();
gJobs.systemChecks = new CronJob({
2019-03-01 11:24:10 -08:00
cronTime: '00 30 * * * *', // every 30 minutes. if you change this interval, change the notification messages with correct duration
onTick: cloudron.runSystemChecks,
2016-12-28 14:21:41 -08:00
start: true,
runOnInit: true, // run system check immediately
2016-12-28 14:21:41 -08:00
timeZone: tz
});
2017-04-12 18:48:14 -07:00
// randomized pattern per cloudron every hour
var randomMinute = Math.floor(60*Math.random());
2016-12-28 14:21:41 -08:00
2017-11-27 12:40:13 -08:00
if (gJobs.boxUpdateCheckerJob) gJobs.boxUpdateCheckerJob.stop();
gJobs.boxUpdateCheckerJob = new CronJob({
2017-04-12 18:48:14 -07:00
cronTime: '00 ' + randomMinute + ' * * * *', // once an hour
2016-12-28 14:21:41 -08:00
onTick: updateChecker.checkBoxUpdates,
start: true,
timeZone: tz
});
2017-11-27 12:40:13 -08:00
if (gJobs.appUpdateChecker) gJobs.appUpdateChecker.stop();
gJobs.appUpdateChecker = new CronJob({
2017-04-12 18:48:14 -07:00
cronTime: '00 ' + randomMinute + ' * * * *', // once an hour
2016-12-28 14:21:41 -08:00
onTick: updateChecker.checkAppUpdates,
start: true,
timeZone: tz
});
2017-11-27 12:40:13 -08:00
if (gJobs.cleanupTokens) gJobs.cleanupTokens.stop();
gJobs.cleanupTokens = new CronJob({
2016-12-28 14:21:41 -08:00
cronTime: '00 */30 * * * *', // every 30 minutes
onTick: janitor.cleanupTokens,
start: true,
timeZone: tz
});
2017-11-27 12:40:13 -08:00
if (gJobs.cleanupBackups) gJobs.cleanupBackups.stop();
gJobs.cleanupBackups = new CronJob({
2017-05-30 16:03:42 -07:00
cronTime: '00 45 */6 * * *', // every 6 hours. try not to overlap with ensureBackup job
2019-01-10 16:00:49 -08:00
onTick: backups.startCleanupTask.bind(null, AUDIT_SOURCE, NOOP_CALLBACK),
2016-12-28 14:21:41 -08:00
start: true,
timeZone: tz
});
2017-11-27 12:40:13 -08:00
if (gJobs.cleanupEventlog) gJobs.cleanupEventlog.stop();
gJobs.cleanupEventlog = new CronJob({
2016-12-28 14:21:41 -08:00
cronTime: '00 */30 * * * *', // every 30 minutes
onTick: eventlog.cleanup,
start: true,
timeZone: tz
});
2017-11-27 12:40:13 -08:00
if (gJobs.dockerVolumeCleaner) gJobs.dockerVolumeCleaner.stop();
gJobs.dockerVolumeCleaner = new CronJob({
2016-12-28 14:21:41 -08:00
cronTime: '00 00 */12 * * *', // every 12 hours
onTick: janitor.cleanupDockerVolumes,
start: true,
timeZone: tz
});
2017-11-27 12:40:13 -08:00
if (gJobs.schedulerSync) gJobs.schedulerSync.stop();
gJobs.schedulerSync = new CronJob({
2016-12-28 14:21:41 -08:00
cronTime: config.TEST ? '*/10 * * * * *' : '00 */1 * * * *', // every minute
onTick: scheduler.sync,
start: true,
timeZone: tz
});
2017-11-27 12:40:13 -08:00
if (gJobs.certificateRenew) gJobs.certificateRenew.stop();
gJobs.certificateRenew = new CronJob({
2016-12-28 14:21:41 -08:00
cronTime: '00 00 */12 * * *', // every 12 hours
2018-12-10 20:20:53 -08:00
onTick: cloudron.renewCerts.bind(null, {}, AUDIT_SOURCE, NOOP_CALLBACK),
2016-12-28 14:21:41 -08:00
start: true,
timeZone: tz
});
2017-07-21 16:13:44 +02:00
2017-11-27 12:40:13 -08:00
if (gJobs.digestEmail) gJobs.digestEmail.stop();
gJobs.digestEmail = new CronJob({
cronTime: '00 00 00 * * 3', // every wednesday
2019-02-20 09:11:45 -08:00
onTick: digest.send,
2017-07-21 16:13:44 +02:00
start: true,
timeZone: tz
});
2018-10-22 11:39:42 -07:00
if (gJobs.appHealthMonitor) gJobs.appHealthMonitor.stop();
gJobs.appHealthMonitor = new CronJob({
cronTime: '*/10 * * * * *', // every 10 seconds
2018-12-16 20:30:09 -08:00
onTick: appHealthMonitor.run.bind(null, 10, NOOP_CALLBACK),
2018-10-22 11:39:42 -07:00
start: true,
timeZone: tz
});
}
function boxAutoupdatePatternChanged(pattern) {
assert.strictEqual(typeof pattern, 'string');
2017-11-27 12:40:13 -08:00
assert(gJobs.boxUpdateCheckerJob);
debug('Box auto update pattern changed to %s', pattern);
if (gJobs.boxAutoUpdater) gJobs.boxAutoUpdater.stop();
if (pattern === constants.AUTOUPDATE_PATTERN_NEVER) return;
gJobs.boxAutoUpdater = new CronJob({
cronTime: pattern,
onTick: function() {
var updateInfo = updateChecker.getUpdateInfo();
if (updateInfo.box) {
2018-02-16 15:58:31 -08:00
debug('Starting autoupdate to %j', updateInfo.box);
2018-07-31 11:35:23 -07:00
updater.updateToLatest(AUDIT_SOURCE, NOOP_CALLBACK);
} else {
debug('No box auto updates available');
}
},
start: true,
timeZone: gJobs.boxUpdateCheckerJob.cronTime.zone // hack
});
}
function appAutoupdatePatternChanged(pattern) {
assert.strictEqual(typeof pattern, 'string');
assert(gJobs.boxUpdateCheckerJob);
debug('Apps auto update pattern changed to %s', pattern);
if (gJobs.appAutoUpdater) gJobs.appAutoUpdater.stop();
if (pattern === constants.AUTOUPDATE_PATTERN_NEVER) return;
gJobs.appAutoUpdater = new CronJob({
cronTime: pattern,
onTick: function() {
var updateInfo = updateChecker.getUpdateInfo();
if (updateInfo.apps) {
2015-07-28 09:37:46 -07:00
debug('Starting app update to %j', updateInfo.apps);
2017-07-31 11:57:23 -07:00
apps.autoupdateApps(updateInfo.apps, AUDIT_SOURCE, NOOP_CALLBACK);
2015-07-28 09:37:46 -07:00
} else {
debug('No app auto updates available');
}
},
start: true,
2017-11-27 12:40:13 -08:00
timeZone: gJobs.boxUpdateCheckerJob.cronTime.zone // hack
});
}
2018-01-25 14:03:42 -08:00
function dynamicDnsChanged(enabled) {
2017-01-02 13:14:03 +01:00
assert.strictEqual(typeof enabled, 'boolean');
2017-11-27 12:40:13 -08:00
assert(gJobs.boxUpdateCheckerJob);
2017-01-02 13:14:03 +01:00
debug('Dynamic DNS setting changed to %s', enabled);
if (enabled) {
2018-11-10 00:18:56 -08:00
gJobs.dynamicDns = new CronJob({
2017-01-02 13:14:03 +01:00
cronTime: '00 */10 * * * *',
2018-01-25 14:03:42 -08:00
onTick: dyndns.sync,
2017-01-02 13:14:03 +01:00
start: true,
2017-11-27 12:40:13 -08:00
timeZone: gJobs.boxUpdateCheckerJob.cronTime.zone // hack
2017-01-02 13:14:03 +01:00
});
} else {
2018-11-10 00:18:56 -08:00
if (gJobs.dynamicDns) gJobs.dynamicDns.stop();
gJobs.dynamicDns = null;
2017-01-02 13:14:03 +01:00
}
}
2018-09-26 12:44:38 -07:00
function stopJobs(callback) {
assert.strictEqual(typeof callback, 'function');
2017-11-27 12:40:13 -08:00
for (var job in gJobs) {
if (!gJobs[job]) continue;
gJobs[job].stop();
gJobs[job] = null;
}
2017-07-21 16:13:44 +02:00
callback();
}