@@ -236,25 +236,35 @@ namespace ts.server {
236236 return `${ d . getHours ( ) } :${ d . getMinutes ( ) } :${ d . getSeconds ( ) } .${ d . getMilliseconds ( ) } ` ;
237237 }
238238
239+ interface QueuedOperation {
240+ operationId : string ;
241+ operation : ( ) => void ;
242+ }
243+
239244 class NodeTypingsInstaller implements ITypingsInstaller {
240245 private installer : NodeChildProcess ;
241246 private installerPidReported = false ;
242247 private socket : NodeSocket ;
243248 private projectService : ProjectService ;
244- private throttledOperations : ThrottledOperations ;
245249 private eventSender : EventSender ;
250+ private activeRequestCount = 0 ;
251+ private requestQueue : QueuedOperation [ ] = [ ] ;
252+ private requestMap = createMap < QueuedOperation > ( ) ; // Maps operation ID to newest requestQueue entry with that ID
253+
254+ private static readonly maxActiveRequestCount = 10 ;
255+ private static readonly requestDelayMillis = 100 ;
256+
246257
247258 constructor (
248259 private readonly telemetryEnabled : boolean ,
249260 private readonly logger : server . Logger ,
250- host : ServerHost ,
261+ private readonly host : ServerHost ,
251262 eventPort : number ,
252263 readonly globalTypingsCacheLocation : string ,
253264 readonly typingSafeListLocation : string ,
254265 readonly typesMapLocation : string ,
255266 private readonly npmLocation : string | undefined ,
256267 private newLine : string ) {
257- this . throttledOperations = new ThrottledOperations ( host ) ;
258268 if ( eventPort ) {
259269 const s = net . connect ( { port : eventPort } , ( ) => {
260270 this . socket = s ;
@@ -338,12 +348,26 @@ namespace ts.server {
338348 this . logger . info ( `Scheduling throttled operation: ${ JSON . stringify ( request ) } ` ) ;
339349 }
340350 }
341- this . throttledOperations . schedule ( project . getProjectName ( ) , /*ms*/ 250 , ( ) => {
351+
352+ const operationId = project . getProjectName ( ) ;
353+ const operation = ( ) => {
342354 if ( this . logger . hasLevel ( LogLevel . verbose ) ) {
343355 this . logger . info ( `Sending request: ${ JSON . stringify ( request ) } ` ) ;
344356 }
345357 this . installer . send ( request ) ;
346- } ) ;
358+ } ;
359+ const queuedRequest : QueuedOperation = { operationId, operation } ;
360+
361+ if ( this . activeRequestCount < NodeTypingsInstaller . maxActiveRequestCount ) {
362+ this . scheduleRequest ( queuedRequest ) ;
363+ }
364+ else {
365+ if ( this . logger . hasLevel ( LogLevel . verbose ) ) {
366+ this . logger . info ( `Deferring request for: ${ operationId } ` ) ;
367+ }
368+ this . requestQueue . push ( queuedRequest ) ;
369+ this . requestMap . set ( operationId , queuedRequest ) ;
370+ }
347371 }
348372
349373 private handleMessage ( response : SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse ) {
@@ -404,11 +428,39 @@ namespace ts.server {
404428 return ;
405429 }
406430
431+ if ( this . activeRequestCount > 0 ) {
432+ this . activeRequestCount -- ;
433+ }
434+ else {
435+ Debug . fail ( "Received too many responses" ) ;
436+ }
437+
438+ while ( this . requestQueue . length > 0 ) {
439+ const queuedRequest = this . requestQueue . shift ( ) ;
440+ if ( this . requestMap . get ( queuedRequest . operationId ) == queuedRequest ) {
441+ this . requestMap . delete ( queuedRequest . operationId ) ;
442+ this . scheduleRequest ( queuedRequest ) ;
443+ break ;
444+ }
445+
446+ if ( this . logger . hasLevel ( LogLevel . verbose ) ) {
447+ this . logger . info ( `Skipping defunct request for: ${ queuedRequest . operationId } ` ) ;
448+ }
449+ }
450+
407451 this . projectService . updateTypingsForProject ( response ) ;
408452 if ( response . kind === ActionSet && this . socket ) {
409453 this . sendEvent ( 0 , "setTypings" , response ) ;
410454 }
411455 }
456+
457+ private scheduleRequest ( request : QueuedOperation ) {
458+ if ( this . logger . hasLevel ( LogLevel . verbose ) ) {
459+ this . logger . info ( `Scheduling request for: ${ request . operationId } ` ) ;
460+ }
461+ this . activeRequestCount ++ ;
462+ this . host . setTimeout ( request . operation , NodeTypingsInstaller . requestDelayMillis ) ;
463+ }
412464 }
413465
414466 class IOSession extends Session {
0 commit comments