diff --git a/server/jobs/mailQueueJob.js b/server/jobs/mailQueueJob.js index 77ab217..1a55264 100644 --- a/server/jobs/mailQueueJob.js +++ b/server/jobs/mailQueueJob.js @@ -2,11 +2,13 @@ angular.module('ffffng').factory('MailQueueJob', function (MailService, Logger) { return { - run: function () { + run: function (callback) { MailService.sendPendingMails(function (err) { if (err) { Logger.tag('mail', 'queue').error('Error sending pending mails:', err); } + + callback(); }); } }; diff --git a/server/jobs/monitoringMailsSendingJob.js b/server/jobs/monitoringMailsSendingJob.js index 72819fc..e630e0a 100644 --- a/server/jobs/monitoringMailsSendingJob.js +++ b/server/jobs/monitoringMailsSendingJob.js @@ -2,11 +2,13 @@ angular.module('ffffng').factory('MonitoringMailsSendingJob', function (MonitoringService, Logger) { return { - run: function () { + run: function (callback) { MonitoringService.sendMonitoringMails(function (err) { if (err) { Logger.tag('monitoring', 'mail-sending').error('Error sending monitoring mails:', err); } + + callback(); }); } }; diff --git a/server/jobs/nodeInformationCleanupJob.js b/server/jobs/nodeInformationCleanupJob.js index df31230..4772c06 100644 --- a/server/jobs/nodeInformationCleanupJob.js +++ b/server/jobs/nodeInformationCleanupJob.js @@ -2,11 +2,13 @@ angular.module('ffffng').factory('NodeInformationCleanupJob', function (MonitoringService, Logger) { return { - run: function () { + run: function (callback) { MonitoringService.cleanupNodeInformation(function (err) { if (err) { Logger.tag('monitoring', 'information-cleanup').error('Error cleaning up node data:', err); } + + callback(); }); } }; diff --git a/server/jobs/nodeInformationRetrievalJob.js b/server/jobs/nodeInformationRetrievalJob.js index 52da5bb..9563fe6 100644 --- a/server/jobs/nodeInformationRetrievalJob.js +++ b/server/jobs/nodeInformationRetrievalJob.js @@ -2,11 +2,13 @@ angular.module('ffffng').factory('NodeInformationRetrievalJob', function (MonitoringService, Logger) { return { - run: function () { + run: function (callback) { MonitoringService.retrieveNodeInformation(function (err) { if (err) { Logger.tag('monitoring', 'information-retrieval').error('Error retrieving node data:', err); } + + callback(); }); } }; diff --git a/server/jobs/scheduler.js b/server/jobs/scheduler.js index c57697f..3734c20 100644 --- a/server/jobs/scheduler.js +++ b/server/jobs/scheduler.js @@ -8,9 +8,18 @@ _.each(jobFiles, function (jobFile) { require(jobFile); }); -angular.module('ffffng').factory('Scheduler', function ($injector, Logger, config) { +angular.module('ffffng').factory('Scheduler', function ($injector, Logger, config, moment) { var cron = require('node-cron'); + var tasks = {}; + + var taskId = 1; + function nextTaskId() { + var id = taskId; + taskId += 1; + return id; + } + function schedule(expr, jobName) { Logger.tag('jobs').info('Scheduling job: %s %s', expr, jobName); @@ -20,7 +29,30 @@ angular.module('ffffng').factory('Scheduler', function ($injector, Logger, confi throw new Error('The job ' + jobName + ' does not provide a "run" function.'); } - cron.schedule(expr, job.run); + var id = nextTaskId(); + var task = { + name: jobName, + schedule: expr, + job: job, + runningSince: false, + lastRunStarted: false + }; + + cron.schedule(expr, function () { + if (task.runningSince) { + // job is still running, skip execution + return; + } + + task.runningSince = moment(); + task.lastRunStarted = task.runningSince; + + job.run(function () { + task.runningSince = false; + }); + }); + + tasks['' + id] = task; } return { @@ -31,6 +63,7 @@ angular.module('ffffng').factory('Scheduler', function ($injector, Logger, confi schedule('0 */1 * * * *', 'MailQueueJob'); if (config.client.monitoring.enabled) { + schedule('* * * * * *', 'TestJob'); schedule('30 */15 * * * *', 'NodeInformationRetrievalJob'); schedule('45 */5 * * * *', 'MonitoringMailsSendingJob'); schedule('0 0 3 * * *', 'NodeInformationCleanupJob'); // every night at 3:00 @@ -42,6 +75,10 @@ angular.module('ffffng').factory('Scheduler', function ($injector, Logger, confi } Logger.tag('jobs').info('Scheduling of background jobs done.'); + }, + + getTasks: function () { + return tasks; } }; }); diff --git a/server/jobs/testJob.js b/server/jobs/testJob.js new file mode 100644 index 0000000..e14a280 --- /dev/null +++ b/server/jobs/testJob.js @@ -0,0 +1,18 @@ +'use strict'; + +angular.module('ffffng').factory('TestJob', function (Logger) { + var i = 1; + + return { + run: function (callback) { + var j = i; + i += 1; + + Logger.tag('test').info('Start test job... ' + j); + setTimeout(function () { + Logger.tag('test').info('Done test job... ' + j); + callback(); + }, 2000); + } + }; +}); diff --git a/server/main.js b/server/main.js index aba2bf9..a72c23f 100644 --- a/server/main.js +++ b/server/main.js @@ -19,6 +19,7 @@ require('./utils/resources'); require('./utils/strings'); require('./utils/urlBuilder'); +require('./resources/taskResource'); require('./resources/nodeResource'); require('./resources/monitoringResource'); diff --git a/server/resources/taskResource.js b/server/resources/taskResource.js new file mode 100644 index 0000000..7648ea0 --- /dev/null +++ b/server/resources/taskResource.js @@ -0,0 +1,21 @@ +'use strict'; + +angular.module('ffffng').factory('TaskResource', function ( + _, + Resources, + Scheduler +) { + return { + getAll: function (req, res) { + var tasks = Scheduler.getTasks(); + return Resources.success(res, _.map(tasks, function (task) { + return { + name: task.name, + schedule: task.schedule, + runningSince: task.runningSince && task.runningSince.unix(), + lastRunStarted: task.lastRunStarted && task.lastRunStarted.unix() + }; + })); + } + }; +}); diff --git a/server/router.js b/server/router.js index 3824651..ca3914c 100644 --- a/server/router.js +++ b/server/router.js @@ -1,6 +1,11 @@ 'use strict'; -angular.module('ffffng').factory('Router', function (app, NodeResource, MonitoringResource) { +angular.module('ffffng').factory('Router', function ( + app, + NodeResource, + MonitoringResource, + TaskResource +) { return { init: function () { app.post('/api/node', NodeResource.create); @@ -10,6 +15,8 @@ angular.module('ffffng').factory('Router', function (app, NodeResource, Monitori app.put('/api/monitoring/confirm/:token', MonitoringResource.confirm); app.put('/api/monitoring/disable/:token', MonitoringResource.disable); + + app.get('/internal/api/task/all', TaskResource.getAll); } }; });