import { AbstractSession , ImperativeError , ImperativeExpect , Logger } from "@zowe/imperative" ; import { inspect } from "util" ; import { GetJobs } from "./GetJobs" ; import { JOB_STATUS , JOB_STATUS_ORDER } from "./types/JobStatus" ; import { sleep } from "@zowe/core-for-zowe-sdk" ; import { IJob } from "./doc/response/IJob" ; import { IMonitorJobWaitForParms } from "./doc/input/IMonitorJobWaitForParms" ; export class export class MonitorJobs { static memberof public static readonly DEFAULT_WATCH_DELAY = 3000 ; static memberof public static readonly DEFAULT_STATUS = JOB_STATUS . OUTPUT ; static memberof public static readonly DEFAULT_ATTEMPTS = Infinity ; static param { AbstractSession } session param { IJob } job returns { Promise < IJob > } memberof public static waitForJobOutputStatus ( session , job ) { ImperativeExpect . toNotBeNullOrUndefined ( job , "IJob object (containing jobname and jobid) required" ) ; return MonitorJobs . waitForStatusCommon ( session , { jobname : job . jobname , jobid : job . jobid , status : JOB_STATUS . OUTPUT } ) ; } static param { AbstractSession } session param { string } jobname param { string } jobid returns { Promise < IJob > } memberof public static waitForOutputStatus ( session , jobname , jobid ) { return MonitorJobs . waitForStatusCommon ( session , { jobname , jobid , status : JOB_STATUS . OUTPUT } ) ; } static param { AbstractSession } session param { IMonitorJobWaitForParms } parms returns { Promise < IJob > } memberof public static async waitForStatusCommon ( session , parms ) { ImperativeExpect . toNotBeNullOrUndefined ( parms , "IMonitorJobParms object required" ) ; ImperativeExpect . keysToBeDefinedAndNonBlank ( parms , [ "jobname" ] ) ; ImperativeExpect . keysToBeDefinedAndNonBlank ( parms , [ "jobid" ] ) ; ImperativeExpect . toNotBeNullOrUndefined ( session , "Required session must be defined" ) ; if ( parms . status != null ) { ImperativeExpect . toBeOneOf ( parms . status , JOB_STATUS_ORDER ) ; } if ( parms . attempts != null ) { ImperativeExpect . keysToBeOfType ( parms , "number" , [ "attempts" ] ) ; if ( parms . attempts < 0 ) { throw new ImperativeError ( { msg : `Expect Error: "attempts" must be a positive integer` } ) ; } } if ( parms . watchDelay != null ) { ImperativeExpect . keysToBeOfType ( parms , "number" , [ "watchDelay" ] ) ; if ( parms . watchDelay < 0 ) { throw new ImperativeError ( { msg : `Expect Error: "watchDelay" must be a positive integer` } ) ; } } this . log . info ( `Monitor Jobs - "waitForStatusCommon" API request: ` + `jobname ${ parms . jobname }, jobid ${ parms . jobid }, attempts ${ parms . attempts }, watch delay ${ parms . watchDelay }` ) ; this . log . trace ( `Parameters:\n${ inspect ( parms ) }` ) ; if ( parms . status == null ) { parms . status = MonitorJobs . DEFAULT_STATUS ; } if ( parms . attempts == null ) { parms . attempts = MonitorJobs . DEFAULT_ATTEMPTS ; } let response ; try { response = await MonitorJobs . pollForStatus ( session , parms ) ; } catch ( pollStatusErr ) { if ( pollStatusErr instanceof ImperativeError ) { const details = pollStatusErr . mDetails ; details . msg = this . constructErrorMsg ( parms , pollStatusErr . message ) ; this . log . error ( `${ details . msg }` ) ; throw new ImperativeError ( details ) ; } else { const msg = this . constructErrorMsg ( parms , pollStatusErr . message ) ; this . log . error ( `${ msg }` ) ; throw new ImperativeError ( { msg } ) ; } } this . log . trace ( `Monitor Jobs - "waitForStatusCommon" complete - found expected status of ${ parms . status }` ) ; return response ; } private static type { Logger } memberof private static log : Logger = Logger . getAppLogger ( ) ; private static param { AbstractSession } session param { IMonitorJobWaitForParms } parms returns { Promise < IJob > } memberof private static async pollForStatus ( session , parms ) { const timeoutVal = parms . watchDelay || MonitorJobs . DEFAULT_WATCH_DELAY ; let expectedStatus = false ; let job ; let attempt = 0 ; let shouldContinue = false ; try { do { attempt ++ ; this . log . debug ( `Polling for jobname "${ parms . jobname }" jobid "${ parms . jobid }" status "${ parms . status }" ` + `- attempt "${ attempt }" (max attempts "${ parms . attempts }") ...` ) ; [ expectedStatus , job ] = await MonitorJobs . checkStatus ( session , parms ) ; shouldContinue = ! expectedStatus && ( parms . attempts > 0 && attempt < parms . attempts ) ; if ( shouldContinue ) { this . log . trace ( `Setting timeout for next poll...` ) ; await sleep ( timeoutVal ) ; } } while ( shouldContinue ) ; } catch ( e ) { this . log . error ( "Received error while polling" ) ; this . log . error ( e ) ; throw e ; } if ( ! expectedStatus && parms . attempts > 0 && attempt >= parms . attempts ) { throw new ImperativeError ( { msg : `Error Details: Reached max poll attempts of "${ parms . attempts }"` } ) ; } this . log . debug ( `Expected status "${ parms . status }" found for jobname "${ parms . jobname }" jobid "${ parms . jobid }" ` + `- attempt "${ attempt }" (max attempts "${ parms . attempts }") ...` ) ; return job ; } private static param { AbstractSession } session param { IMonitorJobWaitForParms } parms returns { Promise < boolean > } memberof private static async checkStatus ( session , parms ) { this . log . debug ( `Checking for "${ parms . status }" status for jobname "${ parms . jobname }", jobid "${ parms . jobid }"...` ) ; const job = await GetJobs . getStatusCommon ( session , parms ) ; this . log . debug ( `jobname "${ parms . jobname }" jobid "${ parms . jobid }" has current status of "${ job . status }".` ) ; if ( job . status == null || JOB_STATUS_ORDER . indexOf ( job . status . toUpperCase ( ) as JOB_STATUS ) < 0 ) { this . log . error ( `An unknown status of "${ job . status }" for jobname ${ job . jobname }, jobid ${ job . jobid }, was received.` ) ; throw new ImperativeError ( { msg : `Error Details: An unknown status "${ job . status }" was received.` } ) ; } if ( JOB_STATUS_ORDER . indexOf ( job . status as JOB_STATUS ) >= JOB_STATUS_ORDER . indexOf ( parms . status ) ) { this . log . debug ( `The current status (${ job . status }) for jobname ${ job . jobname }, jobid ${ job . jobid } ` + `is greater than or equal to the expected of "${ parms . status }"` ) ; return [ true , job ] ; } return [ false , job ] ; } private static param { IMonitorJobWaitForParms } parms param { string } details returns { string } memberof private static constructErrorMsg ( parms , details ) { return `Error obtaining status for jobname "${ parms . jobname }" jobid "${ parms . jobid }".\n${ details }` ; } }