fix(queue): await real process exit before cleanup
Start process-exit waits only when pause or cancellation begins, escalate stubborn children without resolving before close, latch pause across late registrations and fast resume, and retry concat only after a complete resume. Add real child-process and filesystem integration coverage for pause, shutdown cleanup, and persistence order.
This commit is contained in:
@@ -12,7 +12,7 @@ function deferred(): { promise: Promise<void>; resolve: () => void } {
|
||||
function createResource(wait: Promise<void> = Promise.resolve()): QueueProcessResource {
|
||||
return {
|
||||
kill: vi.fn(),
|
||||
wait,
|
||||
wait: () => wait,
|
||||
pause: vi.fn(),
|
||||
resume: vi.fn(),
|
||||
cancel: vi.fn(async () => undefined),
|
||||
@@ -70,6 +70,37 @@ describe('QueueProcessRegistry', () => {
|
||||
expect(registry.isPaused('item-a')).toBe(false);
|
||||
});
|
||||
|
||||
it('keeps pause latched until existing and newly registered resources finish pausing', async () => {
|
||||
const registry = new QueueProcessRegistry();
|
||||
const firstPaused = deferred();
|
||||
const latePaused = deferred();
|
||||
const first = createResource();
|
||||
const late = createResource();
|
||||
first.pause = vi.fn(() => firstPaused.promise);
|
||||
late.pause = vi.fn(() => latePaused.promise);
|
||||
|
||||
registry.register('item-a', 'merge', first);
|
||||
const pausing = registry.pauseItem('item-a');
|
||||
registry.register('item-a', 'post-processing', late);
|
||||
const resuming = registry.resumeItem('item-a');
|
||||
|
||||
await Promise.resolve();
|
||||
expect(registry.isPaused('item-a')).toBe(true);
|
||||
expect(first.resume).not.toHaveBeenCalled();
|
||||
expect(late.pause).toHaveBeenCalledOnce();
|
||||
|
||||
firstPaused.resolve();
|
||||
await Promise.resolve();
|
||||
expect(registry.isPaused('item-a')).toBe(true);
|
||||
|
||||
latePaused.resolve();
|
||||
await Promise.all([pausing, resuming]);
|
||||
|
||||
expect(first.resume).toHaveBeenCalledOnce();
|
||||
expect(late.resume).toHaveBeenCalledOnce();
|
||||
expect(registry.isPaused('item-a')).toBe(false);
|
||||
});
|
||||
|
||||
it.each(['merge', 'split'] as const)('waits for %s termination before removing partial output', async (phase) => {
|
||||
const registry = new QueueProcessRegistry();
|
||||
const closed = deferred();
|
||||
|
||||
Reference in New Issue
Block a user