import Logger from '../../../tools/env.logger' ; import guid from '../../../tools/tools.guid' ; import State from '../state' ; import { CancelablePromise } from '../../../tools/promise.cancelable' ; import ServiceStreams from '../../../services/service.streams' ; import { OperationCharting , IMatch } from './operation.charting' ; import { OperationAppend } from './operation.append' ; export type TChartData = { [ key ] : IMatch [ ] ; } ; export { IMatch } ; export interface IChartRequest { regExp : RegExp ; groups : boolean ; } export interface IRange { from : number ; to : number ; } export class ChartingEngine { private _logger : Logger ; private _state : State ; private _stock : { charting : Map < string , CancelablePromise < TChartData , void > > ; } = { charting : new Map ( ) , } ; private _operations : { charting : OperationCharting ; appending : OperationAppend ; } ; constructor ( state ) { this . _state = state ; this . _logger = new Logger ( `ControllerChartEngine: ${ this . _state . getGuid ( ) }` ) ; this . _operations = { charting : new OperationCharting ( this . _state . getGuid ( ) , this . _state . getStreamFile ( ) ) , appending : new OperationAppend ( this . _state . getGuid ( ) , this . _state . getStreamFile ( ) ) , } ; } public destroy ( ) { return new Promise ( ( resolve , reject ) => { this . cancel ( ) ; resolve ( ) ; } ) ; } public extract ( requests , from ? , to ? , rowOffset ? ) { if ( this . _stock . charting . size !== 0 ) { return new Error ( `Fail to start extracting chart's values because previous wasn't finished.` ) ; } const taskId = guid ( ) ; const measure = this . _logger . measure ( `extracting chart's values` ) ; ServiceStreams . addProgressSession ( taskId , 'chart buidling' , this . _state . getGuid ( ) ) ; ServiceStreams . updateProgressSession ( taskId , 0 , this . _state . getGuid ( ) ) ; const stock = new Map ( ) ; return new CancelablePromise < TChartData , void > ( ( resolve , reject , cancel , self ) => { this . _stock . charting . set ( taskId , self ) ; const results = { } ; if ( typeof from !== 'number' || typeof to !== 'number' || rowOffset === undefined ) { this . _operations . appending . dropCursorPosition ( ) ; } requests . forEach ( ( request ) => { const requestTaskId = guid ( ) ; let task ; if ( typeof from === 'number' && typeof to === 'number' && rowOffset !== undefined ) { task = this . _operations . appending . perform ( request . regExp , { from : from , to : to } , rowOffset , request . groups ) ; } else { task = this . _operations . charting . perform ( request . regExp , request . groups ) ; } stock . set ( requestTaskId , task ) ; task . then ( ( matches ) => { const measurePostProcessing = this . _logger . measure ( `charting "${ request . regExp . source }"` ) ; results [ request . regExp . source ] = matches ; measurePostProcessing ( ) ; stock . delete ( requestTaskId ) ; if ( stock . size === 0 ) { return resolve ( results ) ; } } ) . catch ( ( error ) => { this . _logger . warn ( `Fail to inspect request "${ request . regExp . source }" due error: ${ error . message }` ) ; reject ( error ) ; } ) ; } ) ; } ) . cancel ( ( ) => { this . _logger . verbose ( `Inspecting was canceled.` ) ; } ) . finally ( ( ) => { stock . forEach ( ( notFinishedTask ) => { notFinishedTask . break ( ) ; } ) ; stock . clear ( ) ; this . _stock . charting . delete ( taskId ) ; ServiceStreams . removeProgressSession ( taskId , this . _state . getGuid ( ) ) ; measure ( ) ; } ) ; } public cancel ( ) { this . _stock . charting . forEach ( ( task ) => { task . break ( ) ; } ) ; this . _stock . charting . clear ( ) ; } public isWorking ( ) { return this . _stock . charting . size > 0 ; } }