This commit is contained in:
Girish Ramakrishnan
2025-10-08 11:06:24 +02:00
parent 71c52a87ec
commit f3be7aa763
+84 -84
View File
@@ -1,54 +1,5 @@
'use strict';
exports = module.exports = {
get,
add,
update,
setCompleted,
setCompletedByType,
list,
getLogs,
startTask,
stopTask,
stopAllTasks,
removePrivateFields,
_del: del,
// task types. if you add a task here, fill up the function table in taskworker and dashboard constants.js
// '_' prefix is removed for lookup
TASK_APP: 'app',
// "prefix" allows us to locate the tasks of a specific app or backup site
TASK_APP_BACKUP_PREFIX: 'appBackup_',
TASK_FULL_BACKUP_PREFIX: 'backup_', // full backup
TASK_CLEAN_BACKUPS_PREFIX: 'cleanBackups_',
TASK_BOX_UPDATE: 'boxUpdate',
TASK_CHECK_CERTS: 'checkCerts',
TASK_SYNC_DYNDNS: 'syncDyndns',
TASK_PREPARE_DASHBOARD_LOCATION: 'prepareDashboardLocation',
TASK_SYNC_EXTERNAL_LDAP: 'syncExternalLdap',
TASK_CHANGE_MAIL_LOCATION: 'changeMailLocation',
TASK_SYNC_DNS_RECORDS: 'syncDnsRecords',
TASK_CHECK_BACKUP_INTEGRITY: 'checkBackupIntegrity',
// error codes
ESTOPPED: 'stopped',
ECRASHED: 'crashed',
ETIMEOUT: 'timeout',
// testing
_TASK_IDENTITY: 'identity',
_TASK_CRASH: 'crash',
_TASK_ERROR: 'error',
_TASK_SLEEP: 'sleep'
};
const assert = require('node:assert'),
BoxError = require('./boxerror.js'),
database = require('./database.js'),
@@ -140,6 +91,31 @@ async function setCompleted(id, task) {
await update(id, Object.assign({ completed: true }, task));
}
async function list(page, perPage, options) {
assert.strictEqual(typeof page, 'number');
assert.strictEqual(typeof perPage, 'number');
assert.strictEqual(typeof options, 'object');
const data = [];
let query = `SELECT ${TASKS_FIELDS} FROM tasks`;
if (options.type) {
query += ' WHERE TYPE=?';
data.push(options.type);
} else if (options.prefix) {
query += ' WHERE TYPE LIKE ' + mysql.escape(options.prefix + '%');
}
query += ' ORDER BY creationTime DESC, id DESC LIMIT ?,?'; // put latest task first
data.push((page-1)*perPage);
data.push(perPage);
const results = await database.query(query, data);
results.forEach(postProcess);
return results;
}
async function setCompletedByType(type, task) {
assert.strictEqual(typeof type, 'string');
assert.strictEqual(typeof task, 'object');
@@ -158,6 +134,16 @@ async function add(type, args) {
return String(result.insertId);
}
async function stopTask(id) {
assert.strictEqual(typeof id, 'string');
if (!gTasks[id]) throw new BoxError(BoxError.BAD_STATE, 'task is not active');
debug(`stopTask: stopping task ${id}`);
await shell.sudo([ STOP_TASK_CMD, id, ], {}); // note: this is stopping the systemd-run task. the sudo will exit when this exits
}
async function startTask(id, options) {
assert.strictEqual(typeof id, 'string');
assert.strictEqual(typeof options, 'object');
@@ -214,16 +200,6 @@ async function startTask(id, options) {
throw taskError;
}
async function stopTask(id) {
assert.strictEqual(typeof id, 'string');
if (!gTasks[id]) throw new BoxError(BoxError.BAD_STATE, 'task is not active');
debug(`stopTask: stopping task ${id}`);
await shell.sudo([ STOP_TASK_CMD, id, ], {}); // note: this is stopping the systemd-run task. the sudo will exit when this exits
}
async function stopAllTasks() {
const acs = Object.values(gTasks);
debug(`stopAllTasks: ${acs.length} tasks are running. sending abort signal`);
@@ -233,31 +209,6 @@ async function stopAllTasks() {
if (error) debug(`stopAllTasks: error stopping stasks: ${error.message}`);
}
async function list(page, perPage, options) {
assert.strictEqual(typeof page, 'number');
assert.strictEqual(typeof perPage, 'number');
assert.strictEqual(typeof options, 'object');
const data = [];
let query = `SELECT ${TASKS_FIELDS} FROM tasks`;
if (options.type) {
query += ' WHERE TYPE=?';
data.push(options.type);
} else if (options.prefix) {
query += ' WHERE TYPE LIKE ' + mysql.escape(options.prefix + '%');
}
query += ' ORDER BY creationTime DESC, id DESC LIMIT ?,?'; // put latest task first
data.push((page-1)*perPage);
data.push(perPage);
const results = await database.query(query, data);
results.forEach(postProcess);
return results;
}
async function getLogs(task, options) {
assert.strictEqual(typeof task, 'object');
assert(options && typeof options === 'object');
@@ -290,3 +241,52 @@ async function del(id) {
const result = await database.query('DELETE FROM tasks WHERE id = ?', [ id ]);
if (result.affectedRows !== 1) throw new BoxError(BoxError.NOT_FOUND, 'Task not found');
}
exports = module.exports = {
get,
add,
update,
setCompleted,
setCompletedByType,
list,
getLogs,
startTask,
stopTask,
stopAllTasks,
removePrivateFields,
_del: del,
// task types. if you add a task here, fill up the function table in taskworker and dashboard constants.js
// '_' prefix is removed for lookup
TASK_APP: 'app',
// "prefix" allows us to locate the tasks of a specific app or backup site
TASK_APP_BACKUP_PREFIX: 'appBackup_',
TASK_FULL_BACKUP_PREFIX: 'backup_', // full backup
TASK_CLEAN_BACKUPS_PREFIX: 'cleanBackups_',
TASK_BOX_UPDATE: 'boxUpdate',
TASK_CHECK_CERTS: 'checkCerts',
TASK_SYNC_DYNDNS: 'syncDyndns',
TASK_PREPARE_DASHBOARD_LOCATION: 'prepareDashboardLocation',
TASK_SYNC_EXTERNAL_LDAP: 'syncExternalLdap',
TASK_CHANGE_MAIL_LOCATION: 'changeMailLocation',
TASK_SYNC_DNS_RECORDS: 'syncDnsRecords',
TASK_CHECK_BACKUP_INTEGRITY: 'checkBackupIntegrity',
// error codes
ESTOPPED: 'stopped',
ECRASHED: 'crashed',
ETIMEOUT: 'timeout',
// testing
_TASK_IDENTITY: 'identity',
_TASK_CRASH: 'crash',
_TASK_ERROR: 'error',
_TASK_SLEEP: 'sleep'
};