@@ -21,6 +21,7 @@ const requirePackageJsonPath = require.resolve('../packages/dd-trace/src/require
2121const excludeList = arch ( ) === 'arm64' ? [ 'aerospike' , 'couchbase' , 'grpc' , 'oracledb' ] : [ ]
2222const workspaces = new Set ( )
2323const externalDeps = new Map ( )
24+ const packagePromises = new Map ( )
2425
2526Object . keys ( externals ) . forEach ( external => externals [ external ] . forEach ( thing => {
2627 if ( thing . dep ) {
@@ -58,9 +59,14 @@ async function assertPrerequisites () {
5859
5960 const externalNames = Object . keys ( externals ) . filter ( name => moduleNames . includes ( name ) )
6061
61- await Promise . all ( externalNames . map ( name => limit ( async ( ) => {
62- await Promise . all ( externals [ name ] . map ( inst => limit ( ( ) => assertInstrumentation ( inst , true ) ) ) )
63- } ) ) )
62+ const externalInstrumentations = [ ]
63+ for ( const name of externalNames ) {
64+ for ( const inst of externals [ name ] ) {
65+ externalInstrumentations . push ( inst )
66+ }
67+ }
68+
69+ await Promise . all ( externalInstrumentations . map ( inst => limit ( ( ) => assertInstrumentation ( inst , true ) ) ) )
6470
6571 await assertWorkspaces ( )
6672}
@@ -74,16 +80,30 @@ async function assertInstrumentation (instrumentation, external) {
7480 ? [ process . env . PACKAGE_VERSION_RANGE ]
7581 : [ instrumentation . versions || [ ] ] . flat ( )
7682
77- await Promise . all ( versions . map ( async version => {
78- if ( ! version ) return
83+ // Create the unversioned folder (e.g. `versions/bluebird`, `versions/@grpc/proto-loader`) once per module.
84+ // Some tests depend on it, but creating it for every version key caused concurrent writes corrupting package.json.
85+ const unversionedVersion = versions . includes ( '*' ) ? '*' : versions . find ( Boolean )
86+ if ( unversionedVersion ) {
87+ await assertPackageOnce ( instrumentation . name , null , unversionedVersion , external )
88+ }
89+
90+ const versionKeys = new Set ( )
91+
92+ for ( const version of versions ) {
93+ if ( ! version ) continue
7994
8095 if ( version !== '*' ) {
8196 const result = semver . coerce ( version )
8297 if ( ! result ) throw new Error ( `Invalid version: ${ version } ` )
83- await assertModules ( instrumentation . name , result . version , external )
98+ if ( result . version !== version ) versionKeys . add ( result . version )
8499 }
85- await assertModules ( instrumentation . name , version , external )
86- } ) )
100+
101+ versionKeys . add ( version )
102+ }
103+
104+ await Promise . all (
105+ [ ...versionKeys ] . map ( versionKey => assertModules ( instrumentation . name , versionKey , external ) )
106+ )
87107}
88108
89109/**
@@ -94,8 +114,27 @@ async function assertInstrumentation (instrumentation, external) {
94114async function assertModules ( name , version , external ) {
95115 const range = process . env . RANGE
96116 if ( range && ! semver . subset ( version , range ) ) return
97- // Only create versioned folders (`versions/<name>@<versionKey>`).
98- await assertPackage ( name , version , version , external )
117+ await assertPackageOnce ( name , version , version , external )
118+ }
119+
120+ /**
121+ * Memoized wrapper around assertPackage(), keyed by the destination folder path.
122+ * This avoids concurrent writes to the same `versions/<name>` folder when the same module is processed multiple times.
123+ *
124+ * @param {string } name
125+ * @param {string|null } version
126+ * @param {string } dependencyVersionRange
127+ * @param {boolean } external
128+ * @returns {Promise<void> }
129+ */
130+ function assertPackageOnce ( name , version , dependencyVersionRange , external ) {
131+ const key = folder ( name , version )
132+ const existing = packagePromises . get ( key )
133+ if ( existing ) return existing
134+
135+ const promise = assertPackage ( name , version , dependencyVersionRange , external )
136+ packagePromises . set ( key , promise )
137+ return promise
99138}
100139
101140/**
@@ -250,7 +289,7 @@ async function assertWorkspaces () {
250289 license : 'BSD-3-Clause' ,
251290 private : true ,
252291 workspaces : {
253- packages : [ ...workspaces ]
292+ packages : [ ...workspaces ] . sort ( )
254293 }
255294 } , null , 2 ) + '\n' )
256295}
0 commit comments