Skip to content

Commit

Permalink
add timeout for stop lifecycle
Browse files Browse the repository at this point in the history
  • Loading branch information
mshustov committed Feb 5, 2021
1 parent 81e4595 commit 0715d60
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 1 deletion.
44 changes: 44 additions & 0 deletions src/core/server/plugins/plugins_system.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -505,3 +505,47 @@ describe('start', () => {
expect(log.info).toHaveBeenCalledWith(`Starting [2] plugins: [order-1,order-0]`);
});
});

describe('stop', () => {
beforeAll(() => {
jest.useFakeTimers();
});

afterAll(() => {
jest.useRealTimers();
});

it('waits for 30 sec to finish "stop" and move on to the next plugin.', async () => {
const [plugin1, plugin2] = [createPlugin('timeout-stop-1'), createPlugin('timeout-stop-2')].map(
(plugin, index) => {
jest.spyOn(plugin, 'setup').mockResolvedValue(`setup-as-${index}`);
jest.spyOn(plugin, 'start').mockResolvedValue(`started-as-${index}`);
pluginsSystem.addPlugin(plugin);
return plugin;
}
);

const stopSpy1 = jest
.spyOn(plugin1, 'stop')
.mockImplementationOnce(() => new Promise((resolve) => resolve));
const stopSpy2 = jest.spyOn(plugin2, 'stop').mockImplementationOnce(() => Promise.resolve());

mockCreatePluginSetupContext.mockImplementation(() => ({}));

await pluginsSystem.setupPlugins(setupDeps);
const stopPromise = pluginsSystem.stopPlugins();

jest.runAllTimers();
await stopPromise;
expect(stopSpy1).toHaveBeenCalledTimes(1);
expect(stopSpy2).toHaveBeenCalledTimes(1);

expect(loggingSystemMock.collect(logger).warn).toMatchInlineSnapshot(`
Array [
Array [
"\\"timeout-stop-1\\" plugin didn't finish \\"stop\\" in 30sec.",
],
]
`);
});
});
10 changes: 9 additions & 1 deletion src/core/server/plugins/plugins_system.ts
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,15 @@ export class PluginsSystem {
const pluginName = this.satupPlugins.pop()!;

this.log.debug(`Stopping plugin "${pluginName}"...`);
await this.plugins.get(pluginName)!.stop();

const result = (await Promise.race([
this.plugins.get(pluginName)!.stop(),
new Promise((resolve) => setTimeout(() => resolve({ delayed: true }), 30 * Sec)),
])) as { delayed?: boolean };

if (result?.delayed) {
this.log.warn(`"${pluginName}" plugin didn't stop in 30sec., move on to the next.`);
}
}
}

Expand Down

0 comments on commit 0715d60

Please sign in to comment.