diff --git a/public/src/admin/settings/email.js b/public/src/admin/settings/email.js index e6015b3b32..78a058e19d 100644 --- a/public/src/admin/settings/email.js +++ b/public/src/admin/settings/email.js @@ -8,6 +8,11 @@ define('admin/settings/email', ['admin/settings'], function(settings) { module.init = function() { configureEmailTester(); configureEmailEditor(); + + $(window).on('action:admin.settingsLoaded action:admin.settingsSaved', handleDigestHourChange); + $(window).on('action:admin.settingsSaved', function() { + socket.emit('admin.user.restartJobs'); + }); }; function configureEmailTester() { @@ -57,5 +62,30 @@ define('admin/settings/email', ['admin/settings'], function(settings) { }); } + function handleDigestHourChange() { + var hour = parseInt($('#digestHour').val(), 10); + + if (isNaN(hour)) { + hour = 17; + } else if (hour > 23 || hour < 0) { + hour = 0; + } + + socket.emit('meta.getServerTime', {}, function(err, now) { + now = new Date(now); + + $('#serverTime').text(now.toString()); + + now.setHours(parseInt(hour, 10), 0, 0, 0); + + // If adjusted time is in the past, move to next day + if (now.getTime() < Date.now()) { + now.setDate(now.getDate() + 1); + } + + $('#nextDigestTime').text(now.toString()); + }); + } + return module; }); diff --git a/src/socket.io/admin/user.js b/src/socket.io/admin/user.js index 3fd69a8d10..42dcd23266 100644 --- a/src/socket.io/admin/user.js +++ b/src/socket.io/admin/user.js @@ -226,5 +226,8 @@ User.rejectRegistration = function(socket, data, callback) { user.rejectRegistration(data.username, callback); }; +User.restartJobs = function(socket, data, callback) { + user.startJobs(callback); +}; module.exports = User; diff --git a/src/socket.io/meta.js b/src/socket.io/meta.js index 39603c8d0c..e5c114f372 100644 --- a/src/socket.io/meta.js +++ b/src/socket.io/meta.js @@ -68,6 +68,9 @@ function leaveCurrentRoom(socket) { } } - +SocketMeta.getServerTime = function(socket, data, callback) { + // Returns server time in milliseconds + callback(null, Date.now()); +}; module.exports = SocketMeta; diff --git a/src/user/jobs.js b/src/user/jobs.js index 16f6bd4ce8..9c9569dc40 100644 --- a/src/user/jobs.js +++ b/src/user/jobs.js @@ -1,29 +1,69 @@ - 'use strict'; -var winston = require('winston'), - cronJob = require('cron').CronJob, +var winston = require('winston'); +var cronJob = require('cron').CronJob; + +var meta = require('../meta'); - meta = require('../meta'); +var jobs = {}; module.exports = function(User) { - User.startJobs = function() { - new cronJob('0 0 17 * * *', function() { - winston.verbose('[user.startJobs] Digest job (daily) started.'); + User.startJobs = function(callback) { + winston.verbose('[user/jobs] (Re-)starting user jobs...'); + var terminated = 0; + var started = 0; + var digestHour = parseInt(meta.config.digestHour, 10); + + // Fix digest hour if invalid + if (isNaN(digestHour)) { + digestHour = 17; + } else if (digestHour > 23 || digestHour < 0) { + digestHour = 0; + } + + // Terminate any active cron jobs + for(var jobId in jobs) { + if (jobs.hasOwnProperty(jobId)) { + winston.verbose('[user/jobs] Terminating job (' + jobId + ')'); + jobs[jobId].stop(); + delete jobs[jobId]; + ++terminated; + } + } + winston.verbose('[user/jobs] ' + terminated + ' jobs terminated'); + + jobs['digest.daily'] = new cronJob('0 0 ' + digestHour + ' * * *', function() { + winston.verbose('[user/jobs] Digest job (daily) started.'); User.digest.execute('day'); }, null, true); + winston.verbose('[user/jobs] Starting job (digest.daily)'); + ++started; - new cronJob('0 0 17 * * 0', function() { - winston.verbose('[user.startJobs] Digest job (weekly) started.'); + jobs['digest.weekly'] = new cronJob('0 0 ' + digestHour + ' * * 0', function() { + winston.verbose('[user/jobs] Digest job (weekly) started.'); User.digest.execute('week'); }, null, true); + winston.verbose('[user/jobs] Starting job (digest.weekly)'); + ++started; - new cronJob('0 0 17 1 * *', function() { - winston.verbose('[user.startJobs] Digest job (monthly) started.'); + jobs['digest.monthly'] = new cronJob('0 0 ' + digestHour + ' 1 * *', function() { + winston.verbose('[user/jobs] Digest job (monthly) started.'); User.digest.execute('month'); }, null, true); + winston.verbose('[user/jobs] Starting job (digest.monthly)'); + ++started; + + jobs['reset.clean'] = new cronJob('0 0 0 * * *', User.reset.clean, null, true); + winston.verbose('[user/jobs] Starting job (reset.clean)'); + ++started; + + winston.verbose('[user/jobs] ' + started + ' jobs started'); + + if (typeof callback === 'function') { + callback(); + } - new cronJob('0 0 0 * * *', User.reset.clean, null, true); + return; }; }; diff --git a/src/views/admin/settings/email.tpl b/src/views/admin/settings/email.tpl index cb49aa17b5..3b65cbc0a4 100644 --- a/src/views/admin/settings/email.tpl +++ b/src/views/admin/settings/email.tpl @@ -34,14 +34,14 @@
Enter the full email address here, especially if you are using a Google Apps managed domain.
+ Please enter a number representing the hour to send scheduled email digests (e.g. 0
for midnight, 17
for 5:00pm).
+ Keep in mind that this is the hour according to the server itself, and may not exactly match your system clock.
+ The approximate server time is:
+ The next daily digest is scheduled to be sent
+