@@ -235,24 +235,34 @@ namespace ts.server {
235
235
return `${ d . getHours ( ) } :${ d . getMinutes ( ) } :${ d . getSeconds ( ) } .${ d . getMilliseconds ( ) } ` ;
236
236
}
237
237
238
+ interface QueuedOperation {
239
+ operationId : string ;
240
+ operation : ( ) => void ;
241
+ }
242
+
238
243
class NodeTypingsInstaller implements ITypingsInstaller {
239
244
private installer : NodeChildProcess ;
240
245
private installerPidReported = false ;
241
246
private socket : NodeSocket ;
242
247
private projectService : ProjectService ;
243
- private throttledOperations : ThrottledOperations ;
244
248
private eventSender : EventSender ;
249
+ private activeRequestCount = 0 ;
250
+ private requestQueue : QueuedOperation [ ] = [ ] ;
251
+ private requestMap = createMap < QueuedOperation > ( ) ; // Maps operation ID to newest requestQueue entry with that ID
252
+
253
+ private static readonly maxActiveRequestCount = 10 ;
254
+ private static readonly requestDelayMillis = 100 ;
255
+
245
256
246
257
constructor (
247
258
private readonly telemetryEnabled : boolean ,
248
259
private readonly logger : server . Logger ,
249
- host : ServerHost ,
260
+ private readonly host : ServerHost ,
250
261
eventPort : number ,
251
262
readonly globalTypingsCacheLocation : string ,
252
263
readonly typingSafeListLocation : string ,
253
264
private readonly npmLocation : string | undefined ,
254
265
private newLine : string ) {
255
- this . throttledOperations = new ThrottledOperations ( host ) ;
256
266
if ( eventPort ) {
257
267
const s = net . connect ( { port : eventPort } , ( ) => {
258
268
this . socket = s ;
@@ -333,12 +343,26 @@ namespace ts.server {
333
343
this . logger . info ( `Scheduling throttled operation: ${ JSON . stringify ( request ) } ` ) ;
334
344
}
335
345
}
336
- this . throttledOperations . schedule ( project . getProjectName ( ) , /*ms*/ 250 , ( ) => {
346
+
347
+ const operationId = project . getProjectName ( ) ;
348
+ const operation = ( ) => {
337
349
if ( this . logger . hasLevel ( LogLevel . verbose ) ) {
338
350
this . logger . info ( `Sending request: ${ JSON . stringify ( request ) } ` ) ;
339
351
}
340
352
this . installer . send ( request ) ;
341
- } ) ;
353
+ } ;
354
+ const queuedRequest : QueuedOperation = { operationId, operation } ;
355
+
356
+ if ( this . activeRequestCount < NodeTypingsInstaller . maxActiveRequestCount ) {
357
+ this . scheduleRequest ( queuedRequest ) ;
358
+ }
359
+ else {
360
+ if ( this . logger . hasLevel ( LogLevel . verbose ) ) {
361
+ this . logger . info ( `Deferring request for: ${ operationId } ` ) ;
362
+ }
363
+ this . requestQueue . push ( queuedRequest ) ;
364
+ this . requestMap . set ( operationId , queuedRequest ) ;
365
+ }
342
366
}
343
367
344
368
private handleMessage ( response : SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes | InitializationFailedResponse ) {
@@ -399,11 +423,39 @@ namespace ts.server {
399
423
return ;
400
424
}
401
425
426
+ if ( this . activeRequestCount > 0 ) {
427
+ this . activeRequestCount -- ;
428
+ }
429
+ else {
430
+ Debug . fail ( "Received too many responses" ) ;
431
+ }
432
+
433
+ while ( this . requestQueue . length > 0 ) {
434
+ const queuedRequest = this . requestQueue . shift ( ) ;
435
+ if ( this . requestMap . get ( queuedRequest . operationId ) == queuedRequest ) {
436
+ this . requestMap . delete ( queuedRequest . operationId ) ;
437
+ this . scheduleRequest ( queuedRequest ) ;
438
+ break ;
439
+ }
440
+
441
+ if ( this . logger . hasLevel ( LogLevel . verbose ) ) {
442
+ this . logger . info ( `Skipping defunct request for: ${ queuedRequest . operationId } ` ) ;
443
+ }
444
+ }
445
+
402
446
this . projectService . updateTypingsForProject ( response ) ;
403
447
if ( response . kind === ActionSet && this . socket ) {
404
448
this . sendEvent ( 0 , "setTypings" , response ) ;
405
449
}
406
450
}
451
+
452
+ private scheduleRequest ( request : QueuedOperation ) {
453
+ if ( this . logger . hasLevel ( LogLevel . verbose ) ) {
454
+ this . logger . info ( `Scheduling request for: ${ request . operationId } ` ) ;
455
+ }
456
+ this . activeRequestCount ++ ;
457
+ this . host . setTimeout ( request . operation , NodeTypingsInstaller . requestDelayMillis ) ;
458
+ }
407
459
}
408
460
409
461
class IOSession extends Session {
0 commit comments