Skip to content

Commit 0da87bf

Browse files
clydinalan-agius4
authored andcommitted
fix(@angular-devkit/build-angular): limit concurrent output file writes with application builder
When using localization with the application builder for a large amount of locales, the number of files that may need to be written to disk can become large. This may be problematic on certain operating systems depending on the open file process limits. To avoid approaching the limit, the number of concurrent writes is now limited to 64.
1 parent 5a27795 commit 0da87bf

File tree

1 file changed

+49
-22
lines changed
  • packages/angular_devkit/build_angular/src/tools/esbuild

1 file changed

+49
-22
lines changed

packages/angular_devkit/build_angular/src/tools/esbuild/utils.ts

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -175,40 +175,67 @@ export function getFeatureSupport(target: string[]): BuildOptions['supported'] {
175175
return supported;
176176
}
177177

178+
const MAX_CONCURRENT_WRITES = 64;
179+
178180
export async function writeResultFiles(
179181
outputFiles: BuildOutputFile[],
180182
assetFiles: { source: string; destination: string }[] | undefined,
181183
outputPath: string,
182184
) {
183185
const directoryExists = new Set<string>();
184-
await Promise.all(
185-
outputFiles.map(async (file) => {
186-
const fullOutputPath = file.fullOutputPath;
186+
187+
// Writes the output file to disk and ensures the containing directories are present
188+
const writeOutputFile = async (file: BuildOutputFile) => {
189+
const fullOutputPath = file.fullOutputPath;
190+
// Ensure output subdirectories exist
191+
const basePath = path.dirname(fullOutputPath);
192+
if (basePath && !directoryExists.has(basePath)) {
193+
await fs.mkdir(path.join(outputPath, basePath), { recursive: true });
194+
directoryExists.add(basePath);
195+
}
196+
// Write file contents
197+
await fs.writeFile(path.join(outputPath, fullOutputPath), file.contents);
198+
};
199+
200+
// Write files in groups of MAX_CONCURRENT_WRITES to avoid too many open files
201+
for (let fileIndex = 0; fileIndex < outputFiles.length; ) {
202+
const groupMax = Math.min(fileIndex + MAX_CONCURRENT_WRITES, outputFiles.length);
203+
204+
const actions = [];
205+
while (fileIndex < groupMax) {
206+
actions.push(writeOutputFile(outputFiles[fileIndex++]));
207+
}
208+
209+
await Promise.all(actions);
210+
}
211+
212+
if (assetFiles?.length) {
213+
const copyAssetFile = async (asset: { source: string; destination: string }) => {
187214
// Ensure output subdirectories exist
188-
const basePath = path.dirname(fullOutputPath);
215+
const destPath = join('browser', asset.destination);
216+
const basePath = path.dirname(destPath);
189217
if (basePath && !directoryExists.has(basePath)) {
190218
await fs.mkdir(path.join(outputPath, basePath), { recursive: true });
191219
directoryExists.add(basePath);
192220
}
193-
// Write file contents
194-
await fs.writeFile(path.join(outputPath, fullOutputPath), file.contents);
195-
}),
196-
);
221+
// Copy file contents
222+
await fs.copyFile(
223+
asset.source,
224+
path.join(outputPath, destPath),
225+
fsConstants.COPYFILE_FICLONE,
226+
);
227+
};
228+
229+
for (let fileIndex = 0; fileIndex < assetFiles.length; ) {
230+
const groupMax = Math.min(fileIndex + MAX_CONCURRENT_WRITES, assetFiles.length);
231+
232+
const actions = [];
233+
while (fileIndex < groupMax) {
234+
actions.push(copyAssetFile(assetFiles[fileIndex++]));
235+
}
197236

198-
if (assetFiles?.length) {
199-
await Promise.all(
200-
assetFiles.map(async ({ source, destination }) => {
201-
// Ensure output subdirectories exist
202-
const destPath = join('browser', destination);
203-
const basePath = path.dirname(destPath);
204-
if (basePath && !directoryExists.has(basePath)) {
205-
await fs.mkdir(path.join(outputPath, basePath), { recursive: true });
206-
directoryExists.add(basePath);
207-
}
208-
// Copy file contents
209-
await fs.copyFile(source, path.join(outputPath, destPath), fsConstants.COPYFILE_FICLONE);
210-
}),
211-
);
237+
await Promise.all(actions);
238+
}
212239
}
213240
}
214241

0 commit comments

Comments
 (0)