@@ -93,6 +93,9 @@ export class PackageManager {
9393 readonly #initializationError?: Error ;
9494 #dependencyCache: Map < string , InstalledPackage > | null = null ;
9595 #version: string | undefined ;
96+ #activeTasks = 0 ;
97+ readonly #pendingTasks: { resolve : ( ) => void ; reject : ( err : unknown ) => void } [ ] = [ ] ;
98+ readonly #maxConcurrent = 5 ;
9699
97100 /**
98101 * Creates a new `PackageManager` instance.
@@ -159,49 +162,72 @@ export class PackageManager {
159162 * @param options Options for the child process.
160163 * @returns A promise that resolves with the standard output and standard error of the command.
161164 */
165+ async #runWithThrottle< T > ( action : ( ) => Promise < T > ) : Promise < T > {
166+ if ( this . #activeTasks >= this . #maxConcurrent) {
167+ await new Promise < void > ( ( resolve , reject ) => {
168+ this . #pendingTasks. push ( { resolve, reject } ) ;
169+ } ) ;
170+ } else {
171+ this . #activeTasks++ ;
172+ }
173+
174+ try {
175+ return await action ( ) ;
176+ } finally {
177+ const next = this . #pendingTasks. shift ( ) ;
178+ if ( next ) {
179+ next . resolve ( ) ;
180+ } else {
181+ this . #activeTasks-- ;
182+ }
183+ }
184+ }
185+
162186 async #run(
163187 args : readonly string [ ] ,
164188 options : { timeout ?: number ; registry ?: string ; cwd ?: string } = { } ,
165189 ) : Promise < { stdout : string ; stderr : string } > {
166- this . ensureInstalled ( ) ;
190+ return this . #runWithThrottle( async ( ) => {
191+ this . ensureInstalled ( ) ;
192+
193+ const { registry, cwd, ...runOptions } = options ;
194+ const finalArgs = [ ...args ] ;
195+ let finalEnv : Record < string , string > | undefined ;
196+
197+ if ( registry ) {
198+ const registryOptions = this . descriptor . getRegistryOptions ?.( registry ) ;
199+ if ( ! registryOptions ) {
200+ throw new Error (
201+ `The configured package manager, '${ this . descriptor . binary } ', does not support a custom registry.` ,
202+ ) ;
203+ }
167204
168- const { registry, cwd, ...runOptions } = options ;
169- const finalArgs = [ ...args ] ;
170- let finalEnv : Record < string , string > | undefined ;
205+ if ( registryOptions . args ) {
206+ finalArgs . push ( ...registryOptions . args ) ;
207+ }
208+ if ( registryOptions . env ) {
209+ finalEnv = registryOptions . env ;
210+ }
211+ }
171212
172- if ( registry ) {
173- const registryOptions = this . descriptor . getRegistryOptions ?.( registry ) ;
174- if ( ! registryOptions ) {
175- throw new Error (
176- `The configured package manager, '${ this . descriptor . binary } ', does not support a custom registry.` ,
213+ const executionDirectory = cwd ?? this . cwd ;
214+ if ( this . options . dryRun ) {
215+ this . options . logger ?. info (
216+ `[DRY RUN] Would execute in [${ executionDirectory } ]: ${ this . descriptor . binary } ${ finalArgs . join ( ' ' ) } ` ,
177217 ) ;
178- }
179218
180- if ( registryOptions . args ) {
181- finalArgs . push ( ...registryOptions . args ) ;
182- }
183- if ( registryOptions . env ) {
184- finalEnv = registryOptions . env ;
219+ return { stdout : '' , stderr : '' } ;
185220 }
186- }
187221
188- const executionDirectory = cwd ?? this . cwd ;
189- if ( this . options . dryRun ) {
190- this . options . logger ?. info (
191- `[DRY RUN] Would execute in [${ executionDirectory } ]: ${ this . descriptor . binary } ${ finalArgs . join ( ' ' ) } ` ,
192- ) ;
222+ const commandResult = await this . host . runCommand ( this . descriptor . binary , finalArgs , {
223+ ...runOptions ,
224+ cwd : executionDirectory ,
225+ stdio : 'pipe' ,
226+ env : finalEnv ,
227+ } ) ;
193228
194- return { stdout : '' , stderr : '' } ;
195- }
196-
197- const commandResult = await this . host . runCommand ( this . descriptor . binary , finalArgs , {
198- ...runOptions ,
199- cwd : executionDirectory ,
200- stdio : 'pipe' ,
201- env : finalEnv ,
229+ return { stdout : commandResult . stdout . trim ( ) , stderr : commandResult . stderr . trim ( ) } ;
202230 } ) ;
203-
204- return { stdout : commandResult . stdout . trim ( ) , stderr : commandResult . stderr . trim ( ) } ;
205231 }
206232
207233 /**
0 commit comments