tasks: add completed flag
in some cases, the tasks are setting percent to 100 and crashing later
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
exports.up = async function (db) {
|
||||
await db.runSql('ALTER TABLE tasks ADD COLUMN completed BOOLEAN DEFAULT false');
|
||||
await db.runSql('UPDATE tasks SET completed=? WHERE percent=?', [ true, 100 ]);
|
||||
};
|
||||
|
||||
exports.down = async function (db) {
|
||||
await db.runSql('ALTER TABLE tasks DROP COLUMN completed');
|
||||
};
|
||||
@@ -251,6 +251,7 @@ CREATE TABLE IF NOT EXISTS tasks(
|
||||
type VARCHAR(32) NOT NULL,
|
||||
argsJson TEXT,
|
||||
pending BOOLEAN DEFAULT true,
|
||||
completed BOOLEAN DEFAULT false,
|
||||
percent INTEGER DEFAULT 0,
|
||||
message TEXT,
|
||||
errorJson TEXT,
|
||||
|
||||
@@ -31,6 +31,7 @@ describe('Tasks API', function () {
|
||||
expect(response.body.active).to.be(false); // finished
|
||||
expect(response.body.success).to.be(true);
|
||||
expect(response.body.result).to.be('ping');
|
||||
expect(response.body.completed).to.be(true);
|
||||
expect(response.body.error).to.be(null);
|
||||
});
|
||||
|
||||
@@ -72,10 +73,11 @@ describe('Tasks API', function () {
|
||||
.query({ access_token: owner.token });
|
||||
|
||||
expect(response.status).to.equal(200);
|
||||
expect(response.body.percent).to.be(100);
|
||||
expect(response.body.percent).to.not.be(100);
|
||||
expect(response.body.active).to.be(false); // finished
|
||||
expect(response.body.success).to.be(false);
|
||||
expect(response.body.result).to.be(null);
|
||||
expect(response.body.completed).to.be(true);
|
||||
expect(response.body.error.message).to.contain('stopped');
|
||||
});
|
||||
|
||||
@@ -94,6 +96,7 @@ describe('Tasks API', function () {
|
||||
expect(response.body.tasks[0].active).to.be(false); // finished
|
||||
expect(response.body.tasks[0].success).to.be(true); // finished
|
||||
expect(response.body.tasks[0].result).to.be('ping');
|
||||
expect(response.body.tasks[0].completed).to.be(true);
|
||||
expect(response.body.tasks[0].error).to.be(null);
|
||||
});
|
||||
});
|
||||
|
||||
+14
-9
@@ -61,7 +61,7 @@ let gTasks = {}; // indexed by task id
|
||||
const START_TASK_CMD = path.join(__dirname, 'scripts/starttask.sh');
|
||||
const STOP_TASK_CMD = path.join(__dirname, 'scripts/stoptask.sh');
|
||||
|
||||
const TASKS_FIELDS = [ 'id', 'type', 'argsJson', 'percent', 'pending', 'message', 'errorJson', 'creationTime', 'resultJson', 'ts' ];
|
||||
const TASKS_FIELDS = [ 'id', 'type', 'argsJson', 'percent', 'pending', 'completed', 'message', 'errorJson', 'creationTime', 'resultJson', 'ts' ];
|
||||
|
||||
function postProcess(task) {
|
||||
assert.strictEqual(typeof task, 'object');
|
||||
@@ -72,6 +72,9 @@ function postProcess(task) {
|
||||
|
||||
task.id = String(task.id);
|
||||
|
||||
task.pending = !!task.pending;
|
||||
task.completed = !!task.completed;
|
||||
|
||||
task.result = JSON.parse(task.resultJson);
|
||||
delete task.resultJson;
|
||||
|
||||
@@ -84,14 +87,14 @@ function postProcess(task) {
|
||||
function updateStatus(result) {
|
||||
assert.strictEqual(typeof result, 'object');
|
||||
|
||||
// result.pending - task is scheduled to run at some point
|
||||
// result.completed - task finished and exit/crash was cleanly collected
|
||||
result.running = !!gTasks[result.id]; // running means actively running
|
||||
result.active = result.running || !!result.pending; // active mean task is 'done' or not. at this point, clients can stop polling this task.
|
||||
|
||||
// we rely on 'percent' to determine success. maybe this can become a db field
|
||||
result.success = result.percent === 100 && !result.error;
|
||||
result.active = result.running || result.pending; // active mean task is 'done' or not. at this point, clients can stop polling this task.
|
||||
result.success = result.completed && !result.error; // if task has completed without an error
|
||||
|
||||
// the error in db will be empty if we didn't get a chance to handle task exit
|
||||
if (!result.active && result.percent !== 100 && !result.error) {
|
||||
if (!result.active && !result.completed && !result.error) {
|
||||
result.error = { message: 'Task was stopped because the server restarted or crashed', code: exports.ECRASHED };
|
||||
}
|
||||
|
||||
@@ -104,6 +107,8 @@ async function get(id) {
|
||||
const result = await database.query(`SELECT ${TASKS_FIELDS} FROM tasks WHERE id = ?`, [ id ]);
|
||||
if (result.length === 0) return null;
|
||||
|
||||
console.log(result[0]);
|
||||
|
||||
return updateStatus(postProcess(result[0]));
|
||||
}
|
||||
|
||||
@@ -135,7 +140,7 @@ async function setCompleted(id, task) {
|
||||
|
||||
debug(`setCompleted - ${id}: ${JSON.stringify(task)}`);
|
||||
|
||||
await update(id, Object.assign({ percent: 100 }, task));
|
||||
await update(id, Object.assign({ completed: true }, task));
|
||||
}
|
||||
|
||||
async function setCompletedByType(type, task) {
|
||||
@@ -181,7 +186,7 @@ async function startTask(id, options) {
|
||||
const [getError, task] = await safe(get(id));
|
||||
|
||||
let taskError = null;
|
||||
if (!getError && task.percent !== 100) { // taskworker crashed or was killed by us
|
||||
if (!getError && !task.completed) { // taskworker crashed or was killed by us
|
||||
if (code === 0) {
|
||||
taskError = {
|
||||
message: `Task ${id} ${timedOut ? 'timed out' : 'stopped'}` ,
|
||||
@@ -289,7 +294,7 @@ async function getLogs(task, options) {
|
||||
|
||||
// removes all fields that are strictly private and should never be returned by API calls
|
||||
function removePrivateFields(task) {
|
||||
return _.pick(task, ['id', 'type', 'percent', 'message', 'error', 'running', 'active', 'creationTime', 'result', 'ts', 'success']);
|
||||
return _.pick(task, ['id', 'type', 'percent', 'message', 'error', 'running', 'completed', 'active', 'creationTime', 'result', 'ts', 'success']);
|
||||
}
|
||||
|
||||
async function del(id) {
|
||||
|
||||
+2
-1
@@ -110,7 +110,8 @@ async function main() {
|
||||
const [runError, result] = await safe(TASKS[task.type].apply(null, task.args.concat(progressCallback)));
|
||||
const progress = {
|
||||
result: result || null,
|
||||
error: runError ? JSON.parse(JSON.stringify(runError, Object.getOwnPropertyNames(runError))) : null
|
||||
error: runError ? JSON.parse(JSON.stringify(runError, Object.getOwnPropertyNames(runError))) : null,
|
||||
percent: 100
|
||||
};
|
||||
|
||||
debug(`Task took ${(new Date() - startTime)/1000} seconds`);
|
||||
|
||||
Reference in New Issue
Block a user