mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
fix(core): Account for waiting jobs during shutdown (#11338)
This commit is contained in:
parent
094ec68d4c
commit
c863abd083
|
@ -56,6 +56,7 @@ describe('ScalingService', () => {
|
||||||
let registerWorkerListenersSpy: jest.SpyInstance;
|
let registerWorkerListenersSpy: jest.SpyInstance;
|
||||||
let scheduleQueueRecoverySpy: jest.SpyInstance;
|
let scheduleQueueRecoverySpy: jest.SpyInstance;
|
||||||
let stopQueueRecoverySpy: jest.SpyInstance;
|
let stopQueueRecoverySpy: jest.SpyInstance;
|
||||||
|
let stopQueueMetricsSpy: jest.SpyInstance;
|
||||||
let getRunningJobsCountSpy: jest.SpyInstance;
|
let getRunningJobsCountSpy: jest.SpyInstance;
|
||||||
|
|
||||||
const bullConstructorArgs = [
|
const bullConstructorArgs = [
|
||||||
|
@ -99,6 +100,9 @@ describe('ScalingService', () => {
|
||||||
scheduleQueueRecoverySpy = jest.spyOn(scalingService, 'scheduleQueueRecovery');
|
scheduleQueueRecoverySpy = jest.spyOn(scalingService, 'scheduleQueueRecovery');
|
||||||
// @ts-expect-error Private method
|
// @ts-expect-error Private method
|
||||||
stopQueueRecoverySpy = jest.spyOn(scalingService, 'stopQueueRecovery');
|
stopQueueRecoverySpy = jest.spyOn(scalingService, 'stopQueueRecovery');
|
||||||
|
|
||||||
|
// @ts-expect-error Private method
|
||||||
|
stopQueueMetricsSpy = jest.spyOn(scalingService, 'stopQueueMetrics');
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('setupQueue', () => {
|
describe('setupQueue', () => {
|
||||||
|
@ -180,15 +184,37 @@ describe('ScalingService', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('stop', () => {
|
describe('stop', () => {
|
||||||
it('should pause queue, wait for running jobs, stop queue recovery', async () => {
|
describe('if main', () => {
|
||||||
|
it('should pause queue, stop queue recovery and queue metrics', async () => {
|
||||||
|
// @ts-expect-error readonly property
|
||||||
|
instanceSettings.instanceType = 'main';
|
||||||
|
await scalingService.setupQueue();
|
||||||
|
// @ts-expect-error readonly property
|
||||||
|
scalingService.queueRecoveryContext.timeout = 1;
|
||||||
|
jest.spyOn(scalingService, 'isQueueMetricsEnabled', 'get').mockReturnValue(true);
|
||||||
|
|
||||||
|
await scalingService.stop();
|
||||||
|
|
||||||
|
expect(getRunningJobsCountSpy).not.toHaveBeenCalled();
|
||||||
|
expect(queue.pause).toHaveBeenCalledWith(true, true);
|
||||||
|
expect(stopQueueRecoverySpy).toHaveBeenCalled();
|
||||||
|
expect(stopQueueMetricsSpy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('if worker', () => {
|
||||||
|
it('should wait for running jobs to finish', async () => {
|
||||||
|
// @ts-expect-error readonly property
|
||||||
|
instanceSettings.instanceType = 'worker';
|
||||||
await scalingService.setupQueue();
|
await scalingService.setupQueue();
|
||||||
jobProcessor.getRunningJobIds.mockReturnValue([]);
|
jobProcessor.getRunningJobIds.mockReturnValue([]);
|
||||||
|
|
||||||
await scalingService.stop();
|
await scalingService.stop();
|
||||||
|
|
||||||
expect(queue.pause).toHaveBeenCalledWith(true, true);
|
|
||||||
expect(stopQueueRecoverySpy).toHaveBeenCalled();
|
|
||||||
expect(getRunningJobsCountSpy).toHaveBeenCalled();
|
expect(getRunningJobsCountSpy).toHaveBeenCalled();
|
||||||
|
expect(queue.pause).not.toHaveBeenCalled();
|
||||||
|
expect(stopQueueRecoverySpy).not.toHaveBeenCalled();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -126,13 +126,23 @@ export class ScalingService {
|
||||||
|
|
||||||
@OnShutdown(HIGHEST_SHUTDOWN_PRIORITY)
|
@OnShutdown(HIGHEST_SHUTDOWN_PRIORITY)
|
||||||
async stop() {
|
async stop() {
|
||||||
|
const { instanceType } = this.instanceSettings;
|
||||||
|
|
||||||
|
if (instanceType === 'main') await this.stopMain();
|
||||||
|
else if (instanceType === 'worker') await this.stopWorker();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async stopMain() {
|
||||||
|
if (this.orchestrationService.isSingleMainSetup) {
|
||||||
await this.queue.pause(true, true); // no more jobs will be picked up
|
await this.queue.pause(true, true); // no more jobs will be picked up
|
||||||
|
|
||||||
this.logger.debug('Queue paused');
|
this.logger.debug('Queue paused');
|
||||||
|
}
|
||||||
|
|
||||||
this.stopQueueRecovery();
|
if (this.queueRecoveryContext.timeout) this.stopQueueRecovery();
|
||||||
this.stopQueueMetrics();
|
if (this.isQueueMetricsEnabled) this.stopQueueMetrics();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async stopWorker() {
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
while (this.getRunningJobsCount() !== 0) {
|
while (this.getRunningJobsCount() !== 0) {
|
||||||
|
|
Loading…
Reference in a new issue