Skip to content

Commit a39a1f8

Browse files
committed
fix(core): add timeout to BackgroundProcessManager.close()
close() hangs forever when jobs depend on unavailable resources (e.g. network down during DataStore subscription teardown). Race _closingPromise against a 10s timeout so it always resolves.
1 parent a279b90 commit a39a1f8

File tree

2 files changed

+29
-0
lines changed

2 files changed

+29
-0
lines changed

packages/core/__tests__/BackgroundProcessManager.test.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,4 +664,21 @@ describe('BackgroundProcessManager', () => {
664664
unblock?.();
665665
await close;
666666
});
667+
668+
test('close() resolves after timeout even if jobs never complete', async () => {
669+
const manager = new BackgroundProcessManager();
670+
671+
manager.add(
672+
() => new Promise<void>(() => {}),
673+
'hanging job',
674+
);
675+
676+
const start = Date.now();
677+
await manager.close();
678+
const elapsed = Date.now() - start;
679+
680+
expect(manager.isClosed).toBe(true);
681+
// should resolve around the 10s internal timeout, not hang forever
682+
expect(elapsed).toBeLessThan(15_000);
683+
}, 20_000);
667684
});

packages/core/src/BackgroundProcessManager/BackgroundProcessManager.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,7 +389,19 @@ export class BackgroundProcessManager {
389389
Array.from(this.jobs).map(j => j.promise),
390390
);
391391

392+
const CLOSE_TIMEOUT_MS = 10_000;
393+
let timer: ReturnType<typeof setTimeout>;
394+
const timeoutPromise = new Promise<PromiseSettledResult<any>[]>(
395+
resolve => {
396+
timer = setTimeout(() => resolve([]), CLOSE_TIMEOUT_MS);
397+
},
398+
);
399+
this._closingPromise = Promise.race([
400+
this._closingPromise,
401+
timeoutPromise,
402+
]);
392403
await this._closingPromise;
404+
clearTimeout(timer!);
393405
this._state = BackgroundProcessManagerState.Closed;
394406
}
395407

0 commit comments

Comments
 (0)