Commit 415567dd authored by Cage, Gregory's avatar Cage, Gregory
Browse files

Refactor stdout loading in job details screen to keep stdout in memory

parent 42a04dc3
Loading
Loading
Loading
Loading
Loading
+14 −25
Original line number Diff line number Diff line
<template>
    <div>
        <job-details-provider auto-refresh :jobId="job_id" :page_start=stdout_start :page_end=stdout_end @update:result="updateJob" />
        <job-details-provider auto-refresh :jobId="job_id" :stdout_start=stdout_position :stdout_char_count=stdout_char_count @update:result="updateJob" />
        <h3>Job Information</h3>
        <table id="job-information" class="tabletip info_data_table">
            <tbody>
@@ -37,7 +37,7 @@
                    </td>
                </tr>
                <code-row v-if="job" id="command-line" :code-label="'Command Line'" :code-item="job.command_line" />
                <code-row v-if="job" id="stdout" :code-label="'Tool Standard Output'" :code-item="job.tool_stdout" />
                <code-row v-if="job" id="stdout" :code-label="'Tool Standard Output'" :code-item="stdout_text" />
                <code-row v-if="job" id="stderr" :code-label="'Tool Standard Error'" :code-item="job.tool_stderr" />
                <code-row
                    v-if="job && job.traceback"
@@ -103,11 +103,9 @@ export default {
    data() {
        return {
            job: null,
            stdout_start: 1,
            stdout_end: 3,
            stdout_page_length: 5000,
            stdout_live: true,
            stdout_old: false,
            stdout_position: 0,
            stdout_char_count: 50000,
            stdout_text: "",
        };
    },
    computed: {
@@ -123,18 +121,14 @@ export default {
    updated() {
        try {
            const stdout_block = document.querySelector("#stdout").querySelector(".code");
            if (stdout_block.scrollTop <= .25 * stdout_block.scrollHeight) {
                this.stdout_live = false;
                this.stdout_old = true;
            } else if (stdout_block.scrollTop >= .75 * stdout_block.scrollHeight) {
                this.stdout_live = true;
                this.stdout_old = false;
            // if user is scrolled above the bottom of the code element, then no need to update the stdout
            if (stdout_block.scrollTop <= stdout_block.scrollHeight - 3000) {
                this.stdout_char_count = 0;
            } else {
                this.stdout_live = false;
                this.stdout_old = false;
                this.stdout_char_count = 50000;
            }
        } catch(exception) {
            console.log("Can not find code div.");
            console.log(exception);
        }
    },
    methods: {
@@ -143,16 +137,11 @@ export default {
        },
        updateJob(job) {
            this.job = job;
            if (this.job.tool_stdout.length >= this.stdout_page_length * 3 && this.stdout_live) {
                this.stdout_start += 1;
                this.stdout_end += 1;
            // Keep stdout in memory and only fetch new text via JobProvider
            if (job.tool_stdout != null) {
                this.stdout_text += job.tool_stdout;
                this.stdout_position += job.tool_stdout.length;
            }
            if (!this.stdout_live && this.stdout_old) {
                this.stdout_start = this.stdout_start > 1 ? this.stdout_start - 1: 1;
                this.stdout_end = this.stdout_end > 3 ? this.stdout_end - 1: 3;
            }


        },
    },
};
+2 −2
Original line number Diff line number Diff line
@@ -5,8 +5,8 @@ import { rethrowSimple } from "utils/simple-error";
import { stateIsTerminal } from "./utils";
import { cleanPaginationParameters } from "./utils";

async function jobDetails({ jobId, page_start = 0, page_end = 0 }) {
    const url = `${getAppRoot()}api/jobs/${jobId}?full=True&stdout_start=${page_start}&stdout_end=${page_end}`;
async function jobDetails({ jobId, stdout_start = 0, stdout_char_count = 0 }) {
    const url = `${getAppRoot()}api/jobs/${jobId}?full=True&stdout_start_pos=${stdout_start}&stdout_count=${stdout_char_count}`;
    try {
        const { data } = await axios.get(url);
        return data;
+6 −8
Original line number Diff line number Diff line
@@ -60,7 +60,6 @@ from galaxy.util.search import (
import traceback
log = logging.getLogger(__name__)

STDOUT_PAGE_SIZE_CHARS = 5000

class JobLock(BaseModel):
    active: bool = Field(title="Job lock status", description="If active, jobs will not dispatch")
@@ -221,7 +220,7 @@ class JobManager:
        )
        return self.job_lock()

    def get_accessible_job(self, trans, decoded_job_id, stdout_start=0, stdout_end=0):
    def get_accessible_job(self, trans, decoded_job_id, stdout_start_pos=-1, stdout_count=0):
        job = trans.sa_session.query(trans.app.model.Job).filter(trans.app.model.Job.id == decoded_job_id).first()
        if job is None:
            raise ObjectNotFound()
@@ -239,18 +238,17 @@ class JobManager:
                    raise ItemAccessibilityException("You are not allowed to rerun this job.")
        trans.sa_session.refresh(job)

        if job.state == job.states.RUNNING and stdout_start > 0:
        # iF stdout_count and stdout_start_pos are good values, then load standard out and add it to status
        if job.state == job.states.RUNNING and stdout_count > 0 and stdout_start_pos > -1:
            try:
                stdout_path = Path(".").parent.parent.parent.parent.parent / "database/jobs_directory/000" / str(
                    job.id) / "outputs/tool_stdout"
                stdout_file = open(stdout_path, "r")
                number_of_pages = stdout_end - stdout_start + 1 if stdout_end > 0 else 1
                stdout_file.seek((stdout_start - 1) * STDOUT_PAGE_SIZE_CHARS)
                job.job_stdout = stdout_file.read(STDOUT_PAGE_SIZE_CHARS * number_of_pages)
                stdout_file.seek(stdout_start_pos)
                job.job_stdout = stdout_file.read(stdout_count)
                job.tool_stdout = job.job_stdout
            except Exception as e:
                log.error("Could not read STDOUT: %s", e)
                log.error(traceback.format_exc())
        return job

    def stop(self, job, message=None):
+5 −3
Original line number Diff line number Diff line
@@ -178,8 +178,8 @@ class FastAPIJobs:
        id: EncodedDatabaseIdField,
        trans: ProvidesUserContext = DependsOnTrans,
        full: Optional[bool] = False,
        stdout_start: Optional[int] = None,
        stdout_end: Optional[int] = None,
        stdout_start_pos: Optional[int] = None,
        stdout_count: Optional[int] = None,
    ) -> Dict[str, Any]:
        """
        Return dictionary containing description of job data
@@ -187,8 +187,10 @@ class FastAPIJobs:
        Parameters
        - id: ID of job to return
        - full: Return extra information ?
        - stdout_start_pos: The index of the character to begine reading stdout from
        - stdout_count: How many characters of stdout to read
        """
        return self.service.show(trans, id, bool(full), int(stdout_start) if stdout_start else 0, int(stdout_end) if stdout_end else 0)
        return self.service.show(trans, id, bool(full), int(stdout_start_pos) if stdout_start_pos else 0, int(stdout_count) if stdout_count else 0)

    @router.get("/api/jobs")
    def index(
+3 −3
Original line number Diff line number Diff line
@@ -48,11 +48,11 @@ class JobsService:
        trans: ProvidesUserContext,
        id: EncodedDatabaseIdField,
        full: bool = False,
        stdout_start: int = 0,
        stdout_end: int = 0,
        stdout_start_pos: int = 0,
        stdout_count: int = 0,
    ) -> Dict[str, Any]:
        id = trans.app.security.decode_id(id)
        job = self.job_manager.get_accessible_job(trans, id, stdout_start, stdout_end)
        job = self.job_manager.get_accessible_job(trans, id, stdout_start_pos, stdout_count)
        return view_show_job(trans, job, bool(full))

    def index(