Skip to content

Commit 2060f1c

Browse files
committed
Add action to remove job checkpoints
1 parent 36cdb69 commit 2060f1c

File tree

6 files changed

+201
-1
lines changed

6 files changed

+201
-1
lines changed

mGAP/resources/views/releaseNotes.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ <h4>Release 2.5:</h4>
22
<ul>
33
<li>This release includes a major change in how we perform variant annotation, <a href="mgap-annotation.view">described in more detail here.</a></li>
44
<li>This release includes 107 additional datasets. The total number of variants dropped relative to release 2.4 due to a change in our filtering. Previously, certain conditions would allow a variant to remain in the dataset, even if no subjects had this genotype. After this correction, ~4m sites were removed, although no genotype calls should be changed.</li>
5+
<li>We introduced an entirely new search feature! The new 'Variant Search' page allows you to perform genome-wide queries based on variant annotations (e.g. predicted coding impact or overlap with databases of human pathogenic variants)</li>
56
</ul>
67

78
<h4>Release 2.4:</h4>

mGAP/resources/web/mGAP/Utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ mGAP.Utils = (function($){
142142
"name": "# Variants",
143143
"mode": "markers",
144144
"x": annotationData,
145-
"y": ["GWAS Associations<br>(GRASP)", "Enhancer Region<br>(FANTOM5)", "Predicted Enhancer<br>(ENCODE)", "Transcription Factor<br>Binding (ENCODE)", "Predicted High<br>Impact (SnpEff)", "Damaging<br>(Polyphen2)", "ClinVar Overlap"],
145+
"y": ["Enhancer Region<br>(FANTOM5)", "Predicted Enhancer<br>(ENCODE)", "Transcription Factor<br>Binding (ENCODE)", "Predicted High<br>Impact (SnpEff)", "Damaging<br>(Polyphen2)", "ClinVar Overlap"],
146146
"type": "bar",
147147
"orientation": "h",
148148
"autobiny": true
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
Ext4.define('Primeseq.window.DeleteJobCheckpointWindow', {
2+
extend: 'Ext.window.Window',
3+
4+
statics: {
5+
buttonHandler: function(dataRegionName){
6+
const checked = LABKEY.DataRegions[dataRegionName].getChecked();
7+
if (!checked.length){
8+
Ext4.Msg.alert('Error', 'No rows selected');
9+
return;
10+
}
11+
12+
Ext4.create('Primeseq.window.DeleteJobCheckpointWindow', {
13+
jobIds: checked,
14+
dataRegionName: dataRegionName,
15+
autoShow: true
16+
});
17+
}
18+
},
19+
20+
initComponent: function(){
21+
Ext4.QuickTips.init();
22+
Ext4.apply(this, {
23+
title: 'Update Job Resources',
24+
width: 600,
25+
bodyStyle: 'padding: 5px;',
26+
items: [{
27+
html: 'This will delete the checkpoint JSON file for the selected pipeline jobs, which will cause them to completely restart, instead of attempting to resume at the last checkpoint. This will only delete a checkpoint file for jobs with a status of error or cancelled.',
28+
border: false,
29+
style: 'padding-bottom: 20px;'
30+
},{
31+
xtype: 'checkbox',
32+
itemId: 'restartJobs',
33+
fieldLabel: 'Restart Jobs',
34+
checked: true
35+
}],
36+
buttons: [{
37+
text: 'Submit',
38+
handler: this.onSubmit,
39+
scope: this
40+
},{
41+
text: 'Cancel',
42+
handler: function (btn) {
43+
btn.up('window').close();
44+
}
45+
}]
46+
});
47+
48+
this.callParent(arguments);
49+
},
50+
51+
onSubmit: function(btn){
52+
Ext4.Msg.wait('Loading...');
53+
var restartJobs = btn.up('window').down('#restartJobs');
54+
55+
LABKEY.Ajax.request({
56+
method: 'POST',
57+
url: LABKEY.ActionURL.buildURL('primeseq', 'deleteJobCheckpoint'),
58+
jsonData: {
59+
jobIds: this.jobIds.join(','),
60+
restartJobs: !!restartJobs
61+
},
62+
scope: this,
63+
success: function(response){
64+
Ext4.Msg.hide();
65+
66+
var jsonResp = LABKEY.Utils.decode(response.responseText);
67+
console.log(jsonResp);
68+
var dataRegionName = this.dataRegionName;
69+
this.close();
70+
71+
Ext4.Msg.alert('Success', 'Jobs updated: ' + jsonResp.jobsUpdated + '<br>Jobs restarted: ' + jsonResp.jobsRestarted, function(){
72+
var dataRegion = LABKEY.DataRegions[dataRegionName];
73+
if (dataRegion){
74+
dataRegion.refresh();
75+
}
76+
}, this);
77+
},
78+
failure: LDK.Utils.getErrorCallback()
79+
});
80+
}
81+
});

primeseq/src/org/labkey/primeseq/PrimeseqController.java

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@
6565
import java.io.IOException;
6666
import java.io.PrintWriter;
6767
import java.util.ArrayList;
68+
import java.util.Arrays;
6869
import java.util.Collection;
6970
import java.util.HashMap;
7071
import java.util.HashSet;
@@ -700,4 +701,98 @@ public void setDeleteMultiLineage(boolean deleteMultiLineage)
700701
_deleteMultiLineage = deleteMultiLineage;
701702
}
702703
}
704+
705+
@RequiresPermission(UpdatePermission.class)
706+
public static class DeleteJobCheckpointAction extends MutatingApiAction<DeleteJobCheckpointForm>
707+
{
708+
@Override
709+
public Object execute(DeleteJobCheckpointForm form, BindException errors) throws Exception
710+
{
711+
String jobIDs = StringUtils.trimToNull(form.getJobIds());
712+
if (jobIDs == null)
713+
{
714+
errors.reject(ERROR_MSG, "No JobIds provided");
715+
return false;
716+
}
717+
718+
int jobsUpdated = 0;
719+
int jobsRestarted = 0;
720+
721+
Set<String> jobs = new HashSet<>(Arrays.asList(jobIDs.split(",")));
722+
for (String id : jobs)
723+
{
724+
int jobId = Integer.parseInt(StringUtils.trimToNull(id));
725+
PipelineStatusFile sf = PipelineService.get().getStatusFile(jobId);
726+
if (sf == null)
727+
{
728+
errors.reject(ERROR_MSG, "Unable to find job: " + id);
729+
return false;
730+
}
731+
732+
if (sf.getFilePath() == null)
733+
{
734+
errors.reject(ERROR_MSG, "Unable to find log file: " + sf.getJobId());
735+
return false;
736+
}
737+
738+
File dir = new File(sf.getFilePath()).getParentFile();
739+
if (!dir.exists())
740+
{
741+
errors.reject(ERROR_MSG, "Unable to find job directory: " + sf.getJobId());
742+
return false;
743+
}
744+
745+
for (String fn : Arrays.asList("processVariantsCheckpoint.json", "alignmentCheckpoint.json", "processSingleCellCheckpoint.json"))
746+
{
747+
File checkpoint = new File(dir, fn);
748+
if (checkpoint.exists())
749+
{
750+
jobsUpdated++;
751+
checkpoint.delete();
752+
753+
break;
754+
}
755+
}
756+
757+
if (form.isRestartJobs())
758+
{
759+
if (PipelineJob.TaskStatus.error.name().equalsIgnoreCase(sf.getStatus()) || PipelineJob.TaskStatus.cancelled.name().equalsIgnoreCase(sf.getStatus()))
760+
{
761+
jobsRestarted++;
762+
PipelineJob job = sf.createJobInstance();
763+
PipelineService.get().queueJob(job);
764+
}
765+
}
766+
}
767+
768+
return new ApiSimpleResponse(Map.of("success", true, "jobsUpdated", jobsUpdated, "jobsRestarted", jobsRestarted));
769+
}
770+
}
771+
772+
public static class DeleteJobCheckpointForm
773+
{
774+
private String _jobIds;
775+
776+
private boolean _restartJobs = false;
777+
778+
public String getJobIds()
779+
{
780+
return _jobIds;
781+
}
782+
783+
public void setJobIds(String jobIds)
784+
{
785+
_jobIds = jobIds;
786+
}
787+
788+
public boolean isRestartJobs()
789+
{
790+
return _restartJobs;
791+
}
792+
793+
public void setRestartJobs(boolean restartJobs)
794+
{
795+
_restartJobs = restartJobs;
796+
}
797+
}
703798
}

primeseq/src/org/labkey/primeseq/PrimeseqModule.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.labkey.primeseq.pipeline.BismarkWrapper;
3838
import org.labkey.primeseq.pipeline.BlastPipelineJobResourceAllocator;
3939
import org.labkey.primeseq.pipeline.ClusterMaintenanceTask;
40+
import org.labkey.primeseq.pipeline.DeleteJobCheckpointButton;
4041
import org.labkey.primeseq.pipeline.ExacloudResourceSettings;
4142
import org.labkey.primeseq.pipeline.GeographicOriginStep;
4243
import org.labkey.primeseq.pipeline.MhcCleanupPipelineJob;
@@ -88,6 +89,7 @@ protected void doStartupAfterSpringConfig(ModuleContext moduleContext)
8889

8990
LDKService.get().registerQueryButton(new UpdateResourcesButton(), "pipeline", "job");
9091
LDKService.get().registerQueryButton(new PerformMhcCleanupButton(), "sequenceanalysis", "sequence_analyses");
92+
LDKService.get().registerQueryButton(new DeleteJobCheckpointButton(), "pipeline", "job");
9193
}
9294

9395
@Override
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package org.labkey.primeseq.pipeline;
2+
3+
import org.labkey.api.ldk.table.SimpleButtonConfigFactory;
4+
import org.labkey.api.module.ModuleLoader;
5+
import org.labkey.api.view.template.ClientDependency;
6+
import org.labkey.primeseq.PrimeseqModule;
7+
8+
import java.util.List;
9+
10+
/**
11+
* User: bimber
12+
* Date: 7/16/2014
13+
* Time: 5:37 PM
14+
*/
15+
public class DeleteJobCheckpointButton extends SimpleButtonConfigFactory
16+
{
17+
public DeleteJobCheckpointButton()
18+
{
19+
super(ModuleLoader.getInstance().getModule(PrimeseqModule.class), "Delete Job Checkpoint(s)", "Primeseq.window.DeleteJobCheckpointWindow.buttonHandler(dataRegionName);", List.of(ClientDependency.supplierFromPath("primeseq/window/DeleteJobCheckpointWindow.js")));
20+
}
21+
}

0 commit comments

Comments
 (0)