Commit ee35008f authored by Cage, Gregory's avatar Cage, Gregory
Browse files

Merge branch 'stop-job-feature' into 'dev'

Stop job feature

See merge request !60
parents fca93af0 fd9356c0
Loading
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -61,6 +61,15 @@
                    @click.stop="onHighlight">
                    <span class="fa fa-sitemap" />
                </b-button>
                <b-button
                    v-if="showStop"
                    class="stop-btn px-1"
                    title="Finish Job Early"
                    size="sm"
                    variant="link"
                    @click.stop="onStop">
                    <span class="fa fa-solid fa-stop" />
                </b-button>
                <b-button v-if="showRerun" class="px-1" title="Help" size="sm" variant="link" @click.stop="onRerun">
                    <span class="fa fa-question" />
                </b-button>
@@ -74,6 +83,7 @@ import { copy as sendToClipboard } from "utils/clipboard";
import { absPath, prependPath } from "@/utils/redirect";
import { downloadUrlMixin } from "./mixins.js";
import DatasetDownload from "./DatasetDownload";
import { stopJob } from "components/History/model/queries";

export default {
    components: {
@@ -120,6 +130,9 @@ export default {
        visualizeUrl() {
            return prependPath(this.itemUrls.visualize);
        },
        showStop() {
            return this.item.state == "running";
        },
    },
    methods: {
        onCopyLink() {
@@ -145,6 +158,20 @@ export default {
        onHighlight() {
            this.$emit("toggleHighlights");
        },
        onStop() {
            stopJob(this.item.creating_job);
            document.querySelector(".stop-btn").classList.add("stopping-job");
        },
    },
};
</script>
<style scoped>
.stopping-job {
    animation: blink-animation .5s steps(5, start) infinite;
}
@keyframes blink-animation {
    to {
        visibility: hidden;
    }
}
</style>
+9 −0
Original line number Diff line number Diff line
@@ -53,6 +53,15 @@ export async function deleteContent(content, deleteParams = {}) {
    return doResponse(response);
}

/**
* Stops job and marks it as complete.
*/
export async function stopJob(job_id) {
    const url = `api/jobs/${job_id}/finish`;
    const response = await axios.put(prependPath(url));
    return doResponse(response);
}

/**
 * Update specific fields on datasets or collections.
 * @param {Object} content content object
+5 −2
Original line number Diff line number Diff line
@@ -739,7 +739,7 @@ class PulsarJobRunner(AsynchronousJobRunner):
                )
            return False

    def stop_job(self, job_wrapper):
    def stop_job(self, job_wrapper, soft_kill=True):
        job = job_wrapper.get_job()
        if not job.job_runner_external_id:
            return
@@ -778,6 +778,9 @@ class PulsarJobRunner(AsynchronousJobRunner):
            job_id = job.job_runner_external_id
            log.debug(f"Attempt remote Pulsar kill of job with url {pulsar_url} and id {job_id}")
            client = self.get_client(job.destination_params, job_id)
            if soft_kill:
                client.kill(soft_kill=soft_kill)
            else:
                client.kill()

    def recover(self, job, job_wrapper):
+12 −0
Original line number Diff line number Diff line
@@ -270,6 +270,18 @@ class JobManager:
        else:
            return False

    def finish_early(self, job):
        if not job.finished:
            try:
                job.mark_stopped(self.app.config.track_jobs_in_database)
                session = self.app.model.session
                with transaction(session):
                    session.commit()
                self.app.job_manager.stop(job, message="")
                return True
            except Exception as e:
                log.error("Job Runner does not support stopping job early.")
        return False

class JobSearch:
    """Search for jobs using tool inputs or other jobs"""
+21 −0
Original line number Diff line number Diff line
@@ -339,6 +339,27 @@ class JobController(BaseGalaxyAPIController, UsesVisualizationMixin):
            exceptions.RequestParameterInvalidException(f"Job with id '{job.tool_id}' is not paused")
        return self.__dictify_associations(trans, job.output_datasets, job.output_library_datasets)

    @expose_api
    def finish(self, trans: ProvidesUserContext, id, **kwd) -> List[dict]:
        """
        * PUT /api/jobs/{id}/finish
            Finished a job regardless of execution status (ie early job finish)

        :type   id: string
        :param  id: Encoded job id

        :rtype:     list of dicts
        :returns:   list of dictionaries containing output dataset associations
        """
        job = self.__get_job(trans, id)
        if not job:
            raise exceptions.ObjectNotFound("Could not access job with the given id")
        if job.state == job.states.RUNNING:
            self.job_manager.finish_early(job)
        else:
            exceptions.RequestParameterInvalidException(f"Job with id '{job.tool_id}' is not running.")
        return self.__dictify_associations(trans, job.output_datasets, job.output_library_datasets)

    @expose_api_anonymous
    def metrics(self, trans: ProvidesUserContext, **kwd):
        """
Loading