import Logger from '../logger/Logger' ; import OnceTask from './OnceTask' ; import Task from './Task' ; import TaskStatus from './TaskStatus' ; export default abstract class BaseTask implements Task { protected taskName = 'BaseTask' ; private parentTask : Task | null = null ; private status : TaskStatus = TaskStatus . IDLE ; abstract run ( ) ; constructor ( protected logger ) { this . run = this . baseRun . bind ( this , this . run ) ; this . cancel = this . baseCancel . bind ( this , this . cancel ) ; } once ( ... dependencies ) { return new OnceTask ( this . logger , this , dependencies ) ; } cancel ( ) { } name ( ) { return this . parentTask ? `${ this . parentTask . name ( ) }/${ this . taskName }` : this . taskName ; } setParent ( parentTask ) { this . parentTask = parentTask ; } protected getStatus ( ) { return this . status ; } protected logAndThrow ( message ) { this . logger . info ( message ) ; throw new Error ( message ) ; } private async baseRun ( originalRun ) { try { const startTime = Date . now ( ) ; this . logger . info ( `running task ${ this . name ( ) }` ) ; switch ( this . status ) { case TaskStatus . RUNNING : this . logAndThrow ( `${ this . name ( ) } is already running` ) ; case TaskStatus . CANCELED : this . logAndThrow ( `${ this . name ( ) } was canceled before running` ) ; case TaskStatus . FINISHED : this . logAndThrow ( `${ this . name ( ) } was already finished` ) ; } this . status = TaskStatus . RUNNING ; await originalRun . call ( this ) ; this . logger . info ( `${ this . name ( ) } took ${ Math . round ( Date . now ( ) - startTime ) } ms` ) ; } catch ( err ) { throw err ; } finally { if ( this . status !== TaskStatus . CANCELED ) { this . status = TaskStatus . FINISHED ; } } } private baseCancel ( originalCancel ) { if ( this . status === TaskStatus . CANCELED || this . status === TaskStatus . FINISHED ) { this . logger . info ( `Not canceling ${ this . name ( ) }: state is ${ this . status }` ) ; return ; } this . logger . info ( `canceling task ${ this . name ( ) }` ) ; this . status = TaskStatus . CANCELED ; originalCancel . call ( this ) ; } }