Added possibility to enable / disable tasks.

This commit is contained in:
baldo 2016-06-05 12:18:37 +02:00
parent 8f8d78d1df
commit 53a0ecd366
7 changed files with 109 additions and 46 deletions

View file

@ -3,6 +3,17 @@
<head> <head>
<title>Knotenverwaltung - Admin-Panel</title> <title>Knotenverwaltung - Admin-Panel</title>
<link rel="stylesheet" href="css/ng-admin.min.css"> <link rel="stylesheet" href="css/ng-admin.min.css">
<style>
.task-enabled {
color: green;
}
.task-disabled {
color: lightcoral;
text-decoration: line-through;
}
</style>
</head> </head>
<body ng-app="ffffngAdmin"> <body ng-app="ffffngAdmin">
<div ui-view></div> <div ui-view></div>

View file

@ -14,6 +14,13 @@ myApp.config(['NgAdminConfigurationProvider', function(NgAdminConfigurationProvi
.baseApiUrl('/internal/api/') .baseApiUrl('/internal/api/')
.debug(true); .debug(true);
function taskClasses(task) {
if (!task) {
return;
}
return task.values.enabled ? 'task-enabled' : 'task-disabled';
}
var tasks = nga.entity('tasks').label('Background-Jobs'); var tasks = nga.entity('tasks').label('Background-Jobs');
tasks tasks
.listView() .listView()
@ -22,14 +29,17 @@ myApp.config(['NgAdminConfigurationProvider', function(NgAdminConfigurationProvi
.batchActions([]) .batchActions([])
.exportFields([]) .exportFields([])
.fields([ .fields([
nga.field('id'), nga.field('id').cssClasses(taskClasses),
nga.field('name'), nga.field('name').cssClasses(taskClasses),
nga.field('schedule'), nga.field('schedule').cssClasses(taskClasses),
nga.field('runningSince').map(formatMoment), nga.field('state').cssClasses(taskClasses),
nga.field('lastRunStarted').map(formatMoment) nga.field('runningSince').map(formatMoment).cssClasses(taskClasses),
nga.field('lastRunStarted').map(formatMoment).cssClasses(taskClasses)
]) ])
.listActions( .listActions(
'<fa-task-action-button action="run" task="entry" label="Run" size="sm"></fa-task-action-button>' '<fa-task-action-button action="run" task="entry" button="primary" label="run" size="sm"></fa-task-action-button> ' +
'<fa-task-action-button disabled="entry.values.enabled" button="success" action="enable" icon="off" task="entry" label="enable" size="sm"></fa-task-action-button> ' +
'<fa-task-action-button disabled="!entry.values.enabled" button="warning" action="disable" icon="off" task="entry" label="disable" size="sm"></fa-task-action-button>'
) )
; ;

View file

@ -5,6 +5,7 @@ angular.module('ffffngAdmin')
var link = function (scope) { var link = function (scope) {
scope.label = scope.label || 'ACTION'; scope.label = scope.label || 'ACTION';
scope.icon = scope.icon || 'play'; scope.icon = scope.icon || 'play';
scope.button = scope.button || 'default';
scope.perform = function () { scope.perform = function () {
var task = scope.task(); var task = scope.task();
@ -28,12 +29,14 @@ angular.module('ffffngAdmin')
'icon': '@', 'icon': '@',
'task': '&', 'task': '&',
'size': '@', 'size': '@',
'label': '@' 'label': '@',
'button': '@',
'disabled': '='
}, },
'template': 'template':
'<a class="btn btn-default" ng-class="size ? \'btn-\' + size : \'\'" ng-click="perform()">' + '<button class="btn btn-{{ button }}" ng-disabled="disabled" ng-class="size ? \'btn-\' + size : \'\'" ng-click="perform()">' +
'<span class="glyphicon glyphicon-{{ icon }}" aria-hidden="true"></span>&nbsp;<span class="hidden-xs">{{ label }}</span>' + '<span class="glyphicon glyphicon-{{ icon }}" aria-hidden="true"></span>&nbsp;<span class="hidden-xs">{{ label }}</span>' +
'</a>' '</button>'
}; };
}); });

View file

@ -35,20 +35,24 @@ angular.module('ffffng').factory('Scheduler', function ($injector, Logger, confi
schedule: expr, schedule: expr,
job: job, job: job,
runningSince: false, runningSince: false,
lastRunStarted: false lastRunStarted: false,
state: 'idle',
enabled: true
}; };
task.run = function () { task.run = function () {
if (task.runningSince) { if (task.runningSince || !task.enabled) {
// job is still running, skip execution // job is still running, skip execution
return; return;
} }
task.runningSince = moment(); task.runningSince = moment();
task.lastRunStarted = task.runningSince; task.lastRunStarted = task.runningSince;
task.state = 'running';
job.run(function () { job.run(function () {
task.runningSince = false; task.runningSince = false;
task.state = 'idle';
}); });
}; };
@ -65,7 +69,6 @@ angular.module('ffffng').factory('Scheduler', function ($injector, Logger, confi
schedule('0 */1 * * * *', 'MailQueueJob'); schedule('0 */1 * * * *', 'MailQueueJob');
if (config.client.monitoring.enabled) { if (config.client.monitoring.enabled) {
schedule('* * * * * *', 'TestJob');
schedule('30 */15 * * * *', 'NodeInformationRetrievalJob'); schedule('30 */15 * * * *', 'NodeInformationRetrievalJob');
schedule('45 */5 * * * *', 'MonitoringMailsSendingJob'); schedule('45 */5 * * * *', 'MonitoringMailsSendingJob');
schedule('0 0 3 * * *', 'NodeInformationCleanupJob'); // every night at 3:00 schedule('0 0 3 * * *', 'NodeInformationCleanupJob'); // every night at 3:00

View file

@ -1,18 +0,0 @@
'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);
}
};
});

View file

@ -17,10 +17,61 @@ angular.module('ffffng').factory('TaskResource', function (
name: task.name, name: task.name,
schedule: task.schedule, schedule: task.schedule,
runningSince: task.runningSince && task.runningSince.unix(), runningSince: task.runningSince && task.runningSince.unix(),
lastRunStarted: task.lastRunStarted && task.lastRunStarted.unix() lastRunStarted: task.lastRunStarted && task.lastRunStarted.unix(),
state: task.state,
enabled: task.enabled
}; };
} }
function withValidTaskId(req, res, callback) {
var id = Strings.normalizeString(Resources.getData(req).id);
if (!isValidId(id)) {
return callback({data: 'Invalid task id.', type: ErrorTypes.badRequest});
}
callback(null, id);
}
function getTask(id, callback) {
var tasks = Scheduler.getTasks();
var task = tasks[id];
if (!task) {
return callback({data: 'Task not found.', type: ErrorTypes.notFound});
}
callback(null, task);
}
function withTask(req, res, callback) {
withValidTaskId(req, res, function (err, id) {
if (err) {
return callback(err);
}
getTask(id, function (err, task) {
if (err) {
return callback(err);
}
callback(null, id, task);
});
});
}
function setTaskEnabled(req, res, enable) {
withTask(req, res, function (err, id, task) {
if (err) {
return Resources.error(res, err);
}
task.enabled = !!enable; // ensure boolean
return Resources.success(res, toExternalTask(task, id));
});
}
return { return {
getAll: function (req, res) { getAll: function (req, res) {
var tasks = Scheduler.getTasks(); var tasks = Scheduler.getTasks();
@ -28,26 +79,27 @@ angular.module('ffffng').factory('TaskResource', function (
}, },
run: function (req, res) { run: function (req, res) {
var id = Strings.normalizeString(Resources.getData(req).id); withTask(req, res, function (err, id, task) {
if (err) {
return Resources.error(res, err);
}
if (!isValidId(id)) { if (task.runningSince) {
return Resources.error(res, {data: 'Invalid task id.', type: ErrorTypes.badRequest}); return Resources.error(res, {data: 'Task already running.', type: ErrorTypes.conflict});
} }
var tasks = Scheduler.getTasks(); task.run();
var task = tasks[id];
if (!task) { return Resources.success(res, toExternalTask(task, id));
return Resources.error(res, {data: 'Task not found.', type: ErrorTypes.notFound}); });
} },
if (task.runningSince) { enable: function (req, res) {
return Resources.error(res, {data: 'Task already running.', type: ErrorTypes.conflict}); setTaskEnabled(req, res, true);
} },
task.run(); disable: function (req, res) {
setTaskEnabled(req, res, false);
return Resources.success(res, toExternalTask(task, id));
} }
}; };
}); });

View file

@ -18,6 +18,8 @@ angular.module('ffffng').factory('Router', function (
app.get('/internal/api/tasks', TaskResource.getAll); app.get('/internal/api/tasks', TaskResource.getAll);
app.put('/internal/api/tasks/run/:id', TaskResource.run); app.put('/internal/api/tasks/run/:id', TaskResource.run);
app.put('/internal/api/tasks/enable/:id', TaskResource.enable);
app.put('/internal/api/tasks/disable/:id', TaskResource.disable);
} }
}; };
}); });