diff --git a/server/jobs/scheduler.js b/server/jobs/scheduler.js index 3734c20..84ce8b6 100644 --- a/server/jobs/scheduler.js +++ b/server/jobs/scheduler.js @@ -38,7 +38,7 @@ angular.module('ffffng').factory('Scheduler', function ($injector, Logger, confi lastRunStarted: false }; - cron.schedule(expr, function () { + task.run = function () { if (task.runningSince) { // job is still running, skip execution return; @@ -50,7 +50,9 @@ angular.module('ffffng').factory('Scheduler', function ($injector, Logger, confi job.run(function () { task.runningSince = false; }); - }); + }; + + cron.schedule(expr, task.run); tasks['' + id] = task; } diff --git a/server/resources/taskResource.js b/server/resources/taskResource.js index 7648ea0..d6e6e7b 100644 --- a/server/resources/taskResource.js +++ b/server/resources/taskResource.js @@ -1,21 +1,52 @@ 'use strict'; angular.module('ffffng').factory('TaskResource', function ( + Constraints, + Validator, _, + Strings, Resources, + ErrorTypes, Scheduler ) { + var isValidId = Validator.forConstraint(Constraints.id); + + function toExternalTask(task) { + return { + name: task.name, + schedule: task.schedule, + runningSince: task.runningSince && task.runningSince.unix(), + lastRunStarted: task.lastRunStarted && task.lastRunStarted.unix() + }; + } + 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() - }; - })); + return Resources.success(res, _.mapValues(tasks, toExternalTask)); + }, + + run: function (req, res) { + var id = Strings.normalizeString(Resources.getData(req).id); + + if (!isValidId(id)) { + return Resources.error(res, {data: 'Invalid task id.', type: ErrorTypes.badRequest}); + } + + var tasks = Scheduler.getTasks(); + var task = tasks[id]; + + if (!task) { + return Resources.error(res, {data: 'Task not found.', type: ErrorTypes.notFound}); + } + + if (task.runningSince) { + return Resources.error(res, {data: 'Task already running.', type: ErrorTypes.conflict}); + } + + task.run(); + + return Resources.success(res, toExternalTask(task)); } }; }); diff --git a/server/router.js b/server/router.js index ca3914c..afed5a8 100644 --- a/server/router.js +++ b/server/router.js @@ -17,6 +17,7 @@ angular.module('ffffng').factory('Router', function ( app.put('/api/monitoring/disable/:token', MonitoringResource.disable); app.get('/internal/api/task/all', TaskResource.getAll); + app.put('/internal/api/task/run/:id', TaskResource.run); } }; }); diff --git a/shared/validation/constraints.js b/shared/validation/constraints.js index 72ce708..3299073 100644 --- a/shared/validation/constraints.js +++ b/shared/validation/constraints.js @@ -2,6 +2,10 @@ angular.module('ffffng').factory('Constraints', function () { return { + id:{ + regex: /^[1-9][0-9]*/, + optional: false + }, token:{ regex: /^[0-9a-f]{16}$/i, optional: false