Skip to content

Commit d279bd4

Browse files
committed
Feature: Delete Job: Add robustness, and auto-delete all workflow sub-jobs when parent is deleted.
1 parent 446737a commit d279bd4

2 files changed

Lines changed: 49 additions & 4 deletions

File tree

htdocs/js/pages/Job.class.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3054,7 +3054,17 @@ Page.Job = class Job extends Page.PageUtils {
30543054
var job = this.job;
30553055
if (!app.requirePrivilege('delete_jobs')) return;
30563056

3057-
Dialog.confirmDanger( 'Delete Job', "Are you sure you want to permanently delete the current job, including all logs and files? There is no way to undo this operation.", ['trash-can', 'Delete'], function(result) {
3057+
var title = "Delete Job";
3058+
var text = "Are you sure you want to permanently delete the current job, including all logs and files? There is no way to undo this operation.";
3059+
var btn = ['trash-can', 'Delete'];
3060+
3061+
if (job.type == 'workflow') {
3062+
title = "Delete Workflow Job";
3063+
text += "<br><br>Also, since this is a workflow, note that all sub-jobs will be deleted as well.";
3064+
btn = ['trash-can', 'Delete All'];
3065+
}
3066+
3067+
Dialog.confirmDanger( title, text, btn, function(result) {
30583068
if (!result) return;
30593069
app.clearError();
30603070
Dialog.showProgress( 1.0, "Deleting Job..." );

lib/job.js

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,6 +1865,7 @@ class Jobs {
18651865
deleteJob(job, callback) {
18661866
// delete job record, log and any files
18671867
var self = this;
1868+
this.logJob(5, "Deleting job: " + job.id);
18681869

18691870
// rollback affected stats
18701871
this.rollbackJobStats(job);
@@ -1878,20 +1879,23 @@ class Jobs {
18781879
// delete log file, if present
18791880
if (!job.log_file_size || job.output) return process.nextTick(callback);
18801881
var log_path = 'logs/jobs/' + job.id + '/log.txt.gz';
1881-
self.storage.delete( log_path, callback );
1882+
self.storage.delete( log_path, function(err) {
1883+
self.logError('storage', "" + err);
1884+
callback();
1885+
} );
18821886
},
18831887
function(callback) {
18841888
// delete other files, if any
18851889
if (!job.files || !job.files.length) return process.nextTick(callback);
18861890
var keys = job.files.map( function(file) { return file.path; } );
1887-
self.storage.deleteMulti( keys, callback );
1891+
self.storage.deleteAll( keys, callback );
18881892
},
18891893
function(callback) {
18901894
// delete input files, but only if not attached to buckets/tickets
18911895
if (!job.input || !job.input.files || !job.input.files.length) return process.nextTick(callback);
18921896
var keys = job.input.files.filter( function(file) { return !file.bucket && !file.ticket; } ).map( function(file) { return file.path; } );
18931897
if (!keys.length) return process.nextTick(callback);
1894-
self.storage.deleteMulti( keys, callback );
1898+
self.storage.deleteAll( keys, callback );
18951899
},
18961900
function(callback) {
18971901
// update parent workflow if applicable
@@ -1912,6 +1916,37 @@ class Jobs {
19121916
callback();
19131917
}
19141918
); // unbase.get
1919+
},
1920+
function(callback) {
1921+
// recurse for workflow jobs
1922+
if ((job.type != 'workflow') || !job.workflow || !job.workflow.jobs) return process.nextTick(callback);
1923+
1924+
// collect all sub-job ids from wf
1925+
var job_ids = [];
1926+
for (var node_id in job.workflow.jobs) {
1927+
job.workflow.jobs[node_id].forEach( function(stub) {
1928+
job_ids.push( stub.id );
1929+
} );
1930+
}
1931+
1932+
// workflow may not have completed any jobs
1933+
if (!job_ids.length) return process.nextTick(callback);
1934+
1935+
self.logJob(5, "Deleting all workflow sub-jobs for: " + job.id, { ids: job_ids });
1936+
1937+
async.eachSeries( job_ids, function(job_id, callback) {
1938+
self.unbase.get( 'jobs', job_id, function(err, sub_job) {
1939+
if (err) {
1940+
self.logError('unbase', "" + err);
1941+
return callback();
1942+
}
1943+
1944+
// prevent deleteJob recursion from trying to update parent workflow
1945+
if (sub_job.workflow && sub_job.workflow.job) delete sub_job.workflow.job;
1946+
1947+
self.deleteJob(sub_job, callback);
1948+
} ); // unbase.get
1949+
}, callback); // eachSeries
19151950
}
19161951
], callback ); // async.series
19171952
}

0 commit comments

Comments
 (0)