/**
 * Manages a queue of work to be batch processed at next javascript turn of execution
 */ export class BatchManager < T > { private pendingWork = new Map < string , T [ ] > ( ) ; private pendingTimer : ReturnType < typeof setTimeout > | undefined ; param process constructor ( private readonly process , private readonly maxBatchSize = 100 ) { } param id param work public add ( id , work ) { if ( ! this . pendingWork . has ( id ) ) { this . pendingWork . set ( id , [ ] ) ; } this . pendingWork . get ( id ) ! . push ( work ) ; if ( this . pendingWork . get ( id ) ! . length >= this . maxBatchSize ) { if ( this . pendingTimer !== undefined ) { clearTimeout ( this . pendingTimer ) ; } this . pendingTimer = undefined ; this . startWork ( ) ; } else if ( this . pendingTimer === undefined ) { this . pendingTimer = setTimeout ( ( ) => { this . pendingTimer = undefined ; this . startWork ( ) ; } , 0 ) ; } } /**
     * Process all the pending work item synchronously now
     */ public drain ( ) { this . startWork ( ) ; } private startWork ( ) { const pendingWork = this . pendingWork ; this . pendingWork = new Map < string , T [ ] > ( ) ; for ( const [ id , batch ] of pendingWork ) { this . process ( id , batch ) ; } } }