Skip to content

Commit

Permalink
Flush stdout and stderr before exiting
Browse files Browse the repository at this point in the history
  • Loading branch information
satazor committed Dec 20, 2024
1 parent f1be1dd commit 03f25d1
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ processManager.addHook({

## Debug

Enable verbose debugging by configuring your own logger and passing it to `proccessManager.configure({ log: myCustomLogger })`.
Enable verbose debugging by configuring your own logger and passing it to `processManager.configure({ log: myCustomLogger })`.

The minimum requirements for it to work is that the logger must be Object-like and have functions assigned to properties `info`, `warn`, and `error`.
The functions should be able to handle two different argument signatures:
Expand Down
14 changes: 14 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,8 +198,22 @@ class ProcessManager {

await this.hook('exit', this.errors);

this.log.info('Flushing output');

await this.flushOutput();

this.exit();
}

async flushOutput() {
// Process stdout and stderr can be in non-blocking mode so writes to it may not be flushed when the process exits.
// To ensure that all output is flushed before the process exits, we can write an empty string to stdout and stderr,
// and wait for the write operation to complete.
await Promise.all([
new Promise(resolve => process.stdout.write('', resolve)),
new Promise(resolve => process.stderr.write('', resolve))
]);
}
}

/**
Expand Down
11 changes: 11 additions & 0 deletions test/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ describe('ProcessManager', () => {
jest.spyOn(process, 'exit').mockImplementation(() => {});
jest.spyOn(process, 'on').mockImplementation(() => {});
jest.spyOn(console, 'error').mockImplementation(() => {});
jest.spyOn(process.stderr, 'write').mockImplementation((data, cb) => cb?.());
jest.spyOn(process.stdout, 'write').mockImplementation((data, cb) => cb?.());

const utils = require('../src/utils');

Expand Down Expand Up @@ -291,6 +293,15 @@ describe('ProcessManager', () => {
expect(processManager.hook).toHaveBeenCalledWith('exit', []);
});

test('flushes stdout and stderr', async () => {
await processManager.shutdown();

expect(process.stdout.write).toHaveBeenCalledTimes(1);
expect(process.stdout.write).toHaveBeenCalledWith('', expect.any(Function));
expect(process.stderr.write).toHaveBeenCalledTimes(1);
expect(process.stderr.write).toHaveBeenCalledWith('', expect.any(Function));
});

test('calls `processManager.exit()`', async () => {
jest.spyOn(processManager, 'exit').mockImplementation(() => {});

Expand Down

0 comments on commit 03f25d1

Please sign in to comment.