diff --git a/packages/compiler-cli/ngcc/src/execution/cluster/executor.ts b/packages/compiler-cli/ngcc/src/execution/cluster/executor.ts index f9809bd8e9..23155c3ad3 100644 --- a/packages/compiler-cli/ngcc/src/execution/cluster/executor.ts +++ b/packages/compiler-cli/ngcc/src/execution/cluster/executor.ts @@ -28,13 +28,13 @@ export class ClusterExecutor implements Executor { async execute(analyzeEntryPoints: AnalyzeEntryPointsFn, _createCompileFn: CreateCompileFn): Promise { - return this.lockFile.lock(() => { + return this.lockFile.lock(async () => { this.logger.debug( `Running ngcc on ${this.constructor.name} (using ${this.workerCount} worker processes).`); const master = new ClusterMaster( this.workerCount, this.fileSystem, this.logger, this.fileWriter, this.pkgJsonUpdater, analyzeEntryPoints, this.createTaskCompletedCallback); - return master.run(); + return await master.run(); }); } } diff --git a/packages/compiler-cli/ngcc/src/locking/async_locker.ts b/packages/compiler-cli/ngcc/src/locking/async_locker.ts index 42e1a0604a..f0ea1cebad 100644 --- a/packages/compiler-cli/ngcc/src/locking/async_locker.ts +++ b/packages/compiler-cli/ngcc/src/locking/async_locker.ts @@ -37,7 +37,11 @@ export class AsyncLocker { */ async lock(fn: () => Promise): Promise { await this.create(); - return fn().finally(() => this.lockFile.remove()); + try { + return await fn(); + } finally { + this.lockFile.remove(); + } } protected async create() { diff --git a/packages/compiler-cli/ngcc/test/execution/cluster/executor_spec.ts b/packages/compiler-cli/ngcc/test/execution/cluster/executor_spec.ts index d47d34520c..ce79c66dcd 100644 --- a/packages/compiler-cli/ngcc/test/execution/cluster/executor_spec.ts +++ b/packages/compiler-cli/ngcc/test/execution/cluster/executor_spec.ts @@ -34,7 +34,7 @@ runInEachFileSystem(() => { beforeEach(() => { masterRunSpy = spyOn(ClusterMaster.prototype, 'run') - .and.returnValue(Promise.resolve('CusterMaster#run()' as any)); + .and.returnValue(Promise.resolve('ClusterMaster#run()' as any)); createTaskCompletedCallback = jasmine.createSpy('createTaskCompletedCallback'); mockLogger = new MockLogger(); @@ -63,7 +63,7 @@ runInEachFileSystem(() => { const createCompilerFnSpy = jasmine.createSpy('createCompilerFn'); expect(await executor.execute(analyzeEntryPointsSpy, createCompilerFnSpy)) - .toBe('CusterMaster#run()' as any); + .toBe('ClusterMaster#run()' as any); expect(masterRunSpy).toHaveBeenCalledWith(); @@ -78,6 +78,22 @@ runInEachFileSystem(() => { expect(lockFileLog).toEqual(['write()', 'remove()']); }); + it('should call LockFile.write() and LockFile.remove() if analyzeFn fails', async () => { + const analyzeEntryPointsSpy = + jasmine.createSpy('analyzeEntryPoints').and.throwError('analyze error'); + const createCompilerFnSpy = jasmine.createSpy('createCompilerFn'); + let error = ''; + try { + await executor.execute(analyzeEntryPointsSpy, createCompilerFnSpy); + } catch (e) { + error = e.message; + } + expect(analyzeEntryPointsSpy).toHaveBeenCalledWith(); + expect(createCompilerFnSpy).not.toHaveBeenCalled(); + expect(error).toEqual('analyze error'); + expect(lockFileLog).toEqual(['write()', 'remove()']); + }); + it('should call LockFile.write() and LockFile.remove() if master runner fails', async () => { const anyFn: () => any = () => undefined; masterRunSpy.and.returnValue(Promise.reject(new Error('master runner error')));