Skip to content

Commit cff1c56

Browse files
LucaAndrewKushnir
authored andcommitted
fix(service-worker): file system hash in batch of 500 elements (#45262)
Add file system concurrency hash test Fixes #45133 PR Close #45262
1 parent 6efa366 commit cff1c56

3 files changed

Lines changed: 57 additions & 2 deletions

File tree

packages/service-worker/config/src/generator.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ export class Generator {
6767

6868
// Compute hashes for all matched files and add them to the hash-table.
6969
const allMatchedFiles = ([] as string[]).concat(...Array.from(filesPerGroup.values())).sort();
70-
const allMatchedHashes = await Promise.all(allMatchedFiles.map(file => this.fs.hash(file)));
70+
const allMatchedHashes =
71+
await processInBatches(allMatchedFiles, 500, file => this.fs.hash(file));
7172
allMatchedFiles.forEach((file, idx) => {
7273
hashTable[joinUrls(this.baseHref, file)] = allMatchedHashes[idx];
7374
});
@@ -110,6 +111,20 @@ export function processNavigationUrls(
110111
});
111112
}
112113

114+
async function processInBatches<I, O>(
115+
items: I[], batchSize: number, processFn: (item: I) => O | Promise<O>): Promise<O[]> {
116+
const batches = [];
117+
118+
for (let i = 0; i < items.length; i += batchSize) {
119+
batches.push(items.slice(i, i + batchSize));
120+
}
121+
122+
return batches.reduce(
123+
async (prev, batch) =>
124+
(await prev).concat(await Promise.all(batch.map(item => processFn(item)))),
125+
Promise.resolve<O[]>([]));
126+
}
127+
113128
function globListToMatcher(globs: string[]): (file: string) => boolean {
114129
const patterns = globs.map(pattern => {
115130
if (pattern.startsWith('!')) {

packages/service-worker/config/test/generator_spec.ts

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
import {Generator, processNavigationUrls} from '../src/generator';
1010
import {AssetGroup} from '../src/in';
11-
import {MockFilesystem} from '../testing/mock';
11+
import {HashTrackingMockFilesystem, MockFilesystem} from '../testing/mock';
1212

1313
describe('Generator', () => {
1414
beforeEach(() => spyOn(Date, 'now').and.returnValue(1234567890123));
@@ -355,6 +355,26 @@ describe('Generator', () => {
355355
});
356356
});
357357

358+
it('doesn\'t exceed concurrency limit', async () => {
359+
const fileCount = 600;
360+
const files = [...Array(fileCount).keys()].reduce((acc: Record<string, string>, _, i) => {
361+
acc[`/test${i}.js`] = `This is a test ${i}`;
362+
return acc;
363+
}, {'/index.html': 'This is a test'});
364+
const fs = new HashTrackingMockFilesystem(files);
365+
const gen = new Generator(fs, '/');
366+
const config = await gen.process({
367+
index: '/index.html',
368+
assetGroups: [{
369+
name: 'test',
370+
resources: {files: ['/*.js']},
371+
}],
372+
});
373+
expect(fs.maxConcurrentHashings).toBeLessThanOrEqual(500);
374+
expect(fs.maxConcurrentHashings).toBeGreaterThan(1);
375+
expect(Object.keys((config as any).hashTable).length).toBe(fileCount);
376+
});
377+
358378
describe('processNavigationUrls()', () => {
359379
const customNavigationUrls = [
360380
'https://host/positive/external/**',

packages/service-worker/config/testing/mock.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,23 @@ export class MockFilesystem implements Filesystem {
3232
this.files.set(path, contents);
3333
}
3434
}
35+
36+
export class HashTrackingMockFilesystem extends MockFilesystem {
37+
public maxConcurrentHashings = 0;
38+
private concurrentHashings = 0;
39+
40+
/** @override */
41+
override async hash(path: string): Promise<string> {
42+
// Increase the concurrent hashings count.
43+
this.concurrentHashings += 1;
44+
this.maxConcurrentHashings = Math.max(this.maxConcurrentHashings, this.concurrentHashings);
45+
46+
// Artificial delay to check hashing concurrency.
47+
await new Promise(resolve => setTimeout(resolve, 250));
48+
49+
// Decrease the concurrent hashings count.
50+
this.concurrentHashings -= 1;
51+
52+
return super.hash(path);
53+
}
54+
}

0 commit comments

Comments
 (0)