@@ -12,6 +12,7 @@ import {normalizePathToPosix} from './path-normalize.js';
1212import { readFileSync } from 'fs' ;
1313import { testApiGolden } from './test_api_report.js' ;
1414import * as fs from 'fs' ;
15+ import { Piscina } from 'piscina' ;
1516
1617/** Interface describing contents of a `package.json`. */
1718export interface PackageJson {
@@ -40,11 +41,11 @@ async function main(
4041 const packageJsonPath = path . join ( npmPackageDir , 'package.json' ) ;
4142 const packageJson = JSON . parse ( readFileSync ( packageJsonPath , 'utf8' ) ) as PackageJson ;
4243 const entryPoints = findEntryPointsWithinNpmPackage ( npmPackageDir , packageJson ) ;
43- const outdatedGoldens : string [ ] = [ ] ;
44-
45- let allTestsSucceeding = true ;
44+ const worker = new Piscina < Parameters < typeof testApiGolden > , string > ( {
45+ filename : path . resolve ( __dirname , './test_api_report.js' ) ,
46+ } ) ;
4647
47- for ( const { subpath, typesEntryPointPath} of entryPoints ) {
48+ const processEntryPoint = async ( subpath : string , typesEntryPointPath : string ) => {
4849 // API extractor generates API reports as markdown files. For each types
4950 // entry-point we maintain a separate golden file. These golden files are
5051 // based on the name of the defining NodeJS exports subpath in the NPM package,
@@ -53,32 +54,54 @@ async function main(
5354 const goldenFilePath = path . join ( goldenDir , goldenName ) ;
5455 const moduleName = normalizePathToPosix ( path . join ( packageJson . name , subpath ) ) ;
5556
56- const actual = await testApiGolden (
57+ const actual = await worker . run ( [
5758 typesEntryPointPath ,
5859 stripExportPattern ,
5960 typeNames ,
6061 packageJsonPath ,
6162 moduleName ,
62- ) ;
63+ ] ) ;
6364
6465 if ( actual === null ) {
6566 console . error ( `Could not generate API golden for subpath: "${ subpath } ". See errors above.` ) ;
6667 process . exit ( 1 ) ;
6768 }
6869
6970 if ( approveGolden ) {
70- fs . mkdirSync ( path . dirname ( goldenFilePath ) , { recursive : true } ) ;
71- fs . writeFileSync ( goldenFilePath , actual , 'utf8' ) ;
71+ await fs . promises . mkdir ( path . dirname ( goldenFilePath ) , { recursive : true } ) ;
72+ await fs . promises . writeFile ( goldenFilePath , actual , 'utf8' ) ;
7273 } else {
73- const expected = fs . readFileSync ( goldenFilePath , 'utf8' ) ;
74+ const expected = await fs . promises . readFile ( goldenFilePath , 'utf8' ) ;
7475 if ( actual !== expected ) {
7576 // Keep track of outdated goldens for error message.
7677 outdatedGoldens . push ( goldenName ) ;
77- allTestsSucceeding = false ;
78+ return false ;
7879 }
7980 }
81+
82+ return true ;
83+ } ;
84+
85+ const outdatedGoldens : string [ ] = [ ] ;
86+ const tasks : Promise < boolean > [ ] = [ ] ;
87+ // Process in batches. Otherwise we risk out of memory errors.
88+ const batchSize = 10 ;
89+
90+ for ( let i = 0 ; i < entryPoints . length ; i += batchSize ) {
91+ const batchEntryPoints = entryPoints . slice ( i , i + batchSize ) ;
92+
93+ for ( const { subpath, typesEntryPointPath} of batchEntryPoints ) {
94+ tasks . push ( processEntryPoint ( subpath , typesEntryPointPath ) ) ;
95+ }
96+
97+ // Wait for new batch.
98+ await Promise . all ( tasks ) ;
8099 }
81100
101+ // Wait for final batch/retrieve all results.
102+ const results = await Promise . all ( tasks ) ;
103+ const allTestsSucceeding = results . every ( ( r ) => r === true ) ;
104+
82105 if ( outdatedGoldens . length ) {
83106 console . error ( chalk . red ( `The following goldens are outdated:` ) ) ;
84107 outdatedGoldens . forEach ( ( name ) => console . info ( `- ${ name } ` ) ) ;
0 commit comments