diff --git a/server/job/impl/Cook/JobCook.ts b/server/job/impl/Cook/JobCook.ts index e096e0667..cc3f2426b 100644 --- a/server/job/impl/Cook/JobCook.ts +++ b/server/job/impl/Cook/JobCook.ts @@ -406,14 +406,23 @@ export abstract class JobCook extends JobPackrat { if(cookJobReport['state']!=='waiting' && cookJobReport['state']!=='running') LOG.info(`JobCook [${this.name()}] polling [exited], state: ${cookJobReport['state']}: ${requestUrl}`, LOG.LS.eJOB); + // extract our Cook JobID + const cookJobID: string = cookJobReport['id']; + + // depending on our state we handle our state changes switch (cookJobReport['state']) { - case 'created': await this.recordCreated(); break; + case 'created': await this.recordCreated(); break; case 'waiting': await this.recordWaiting(); break; - case 'running': await this.recordStart(); break; + case 'running': await this.recordStart(cookJobID); break; case 'done': await this.recordSuccess(JSON.stringify(cookJobReport)); return { success: true, allowRetry: false, connectFailure: false, otherCookError: false }; case 'error': await this.recordFailure(JSON.stringify(cookJobReport), cookJobReport['error']); return { success: false, allowRetry: false, connectFailure: false, otherCookError: false, error: cookJobReport['error'] }; case 'cancelled': await this.recordCancel(JSON.stringify(cookJobReport), cookJobReport['error']); return { success: false, allowRetry: false, connectFailure: false, otherCookError: false, error: cookJobReport['error'] }; } + + // we always update our output so it represents the latest from Cook + // TODO: measure performance and wrap into staggered updates if needed + await this.updateJobOutput(JSON.stringify(cookJobReport)); + } catch (err) { return this.handleRequestException(err, requestUrl, 'get', undefined); } @@ -701,14 +710,4 @@ export abstract class JobCook extends JobPackrat { // return success return baseName; } - - // private getSceneFilenamesFromMap(fileMap: Map): string[] { - // const result: string[] = []; - // fileMap.forEach((value, _key) => { - // if (value.includes('svx.json')) { - // result.push(value); - // } - // }); - // return result; - // } } diff --git a/server/job/impl/NS/JobPackrat.ts b/server/job/impl/NS/JobPackrat.ts index 5eed8beaf..8f198110a 100644 --- a/server/job/impl/NS/JobPackrat.ts +++ b/server/job/impl/NS/JobPackrat.ts @@ -120,6 +120,14 @@ export abstract class JobPackrat implements JOB.IJob { return await this._report.append(content); } + protected async updateJobOutput(output: string, updateEngines: boolean=false): Promise { + //this._dbJobRun.Result = true; + this._dbJobRun.Output = output; + await this._dbJobRun.update(); + if(updateEngines) + this.updateEngines(true); // don't block + } + protected async recordCreated(): Promise { const updated: boolean = (this._dbJobRun.getStatus() == COMMON.eWorkflowJobRunStatus.eUnitialized); if (updated) { @@ -141,10 +149,10 @@ export abstract class JobPackrat implements JOB.IJob { } } - protected async recordStart(): Promise { + protected async recordStart(idJob: string): Promise { const updated: boolean = (this._dbJobRun.getStatus() != COMMON.eWorkflowJobRunStatus.eRunning); if (updated) { - this.appendToReportAndLog(`JobPackrat [${this.name()}] Starting`); + this.appendToReportAndLog(`JobPackrat [${this.name()}] Starting (CookJobId: ${idJob})`); this._dbJobRun.DateStart = new Date(); this._dbJobRun.setStatus(COMMON.eWorkflowJobRunStatus.eRunning); await this._dbJobRun.update(); @@ -159,8 +167,8 @@ export abstract class JobPackrat implements JOB.IJob { this._results = { success: true }; // do this before we await this._dbJobRun.update() this._dbJobRun.DateEnd = new Date(); this._dbJobRun.Result = true; + this._dbJobRun.Output = output ?? this._dbJobRun.Output; // if we don't have output, keep what we've got. this._dbJobRun.setStatus(COMMON.eWorkflowJobRunStatus.eDone); - this._dbJobRun.Output = output; await this._dbJobRun.update(); if (this._report) { @@ -179,11 +187,19 @@ export abstract class JobPackrat implements JOB.IJob { this.appendToReportAndLog(`JobPackrat [${this.name()}] Failure: ${errorMsg}`, true); this._results = { success: false, error: errorMsg }; // do this before we await this._dbJobRun.update() this._dbJobRun.DateEnd = new Date(); - this._dbJobRun.Result = false; + this._dbJobRun.Result = true; this._dbJobRun.setStatus(COMMON.eWorkflowJobRunStatus.eError); - this._dbJobRun.Output = output; + this._dbJobRun.Output = output ?? this._dbJobRun.Output; // if we don't have output, keep what we've got. this._dbJobRun.Error = errorMsg ?? ''; await this._dbJobRun.update(); + + // make sure we attach our report if there is one + if (this._report) { + const pathDownload: string = RouteBuilder.DownloadJobRun(this._dbJobRun.idJobRun , eHrefMode.ePrependServerURL); + const hrefDownload: string = H.Helpers.computeHref(pathDownload, 'Cook Job Output'); + await this._report.append(`${hrefDownload}
\n`); + } + this.updateEngines(true, true); // don't block } } @@ -197,18 +213,26 @@ export abstract class JobPackrat implements JOB.IJob { } else this.appendToReportAndLog(`JobPackrat [${this.name()}] Cancel`, true); + console.log(`>>> cancel: ${output}`); this._results = { success: false, error: 'Job Cancelled' + (errorMsg ? ` ${errorMsg}` : '') }; // do this before we await this._dbJobRun.update() this._dbJobRun.DateEnd = new Date(); - this._dbJobRun.Result = false; + this._dbJobRun.Result = true; this._dbJobRun.setStatus(COMMON.eWorkflowJobRunStatus.eCancelled); - this._dbJobRun.Output = output; + this._dbJobRun.Output = output ?? this._dbJobRun.Output; // if we don't have output, keep what we've got. await this._dbJobRun.update(); + + // make sure we attach our report if there is one + if (this._report) { + const pathDownload: string = RouteBuilder.DownloadJobRun(this._dbJobRun.idJobRun , eHrefMode.ePrependServerURL); + const hrefDownload: string = H.Helpers.computeHref(pathDownload, 'Cook Job Output'); + await this._report.append(`${hrefDownload}
\n`); + } + this.updateEngines(true, true); // don't block } } protected async logError(errorMessage: string, addToReport: boolean = true): Promise { - // const error: string = `JobCookSIGenerateDownloads.${errorMessage}`; // TODO: prepend with recipe type/info/jobId. overriden by each derived class const error = `[${this.name()}] ${errorMessage}`; if(addToReport == true)