Cancel esAdapter.wait() on stop (#134727)

This commit is contained in:
Gerard Soldevila 2022-06-28 09:30:59 +02:00 committed by GitHub
parent c4350f1f2a
commit 52bf9eefb4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 50 additions and 2 deletions

View file

@ -8,9 +8,18 @@
import { createEsContext } from './context';
import { Logger } from '@kbn/core/server';
import { elasticsearchServiceMock, loggingSystemMock } from '@kbn/core/server/mocks';
import { createReadySignal } from '../lib/ready_signal';
jest.mock('../lib/../../../../package.json', () => ({ version: '1.2.3' }));
jest.mock('./init');
jest.mock('../lib/ready_signal', () => {
const createReadySignalActual = jest.requireActual('../lib/ready_signal');
return {
createReadySignal: jest.fn(createReadySignalActual.createReadySignal),
};
});
const mockCreateReadySignal = createReadySignal as jest.MockedFunction<typeof createReadySignal>;
let logger: Logger;
let elasticsearchClient: ReturnType<typeof elasticsearchServiceMock.createElasticsearchClient>;
@ -99,6 +108,31 @@ describe('createEsContext', () => {
expect(doesIndexTemplateExist).toBeTruthy();
});
test('should cancel initialization in case of server shutdown', async () => {
const readySignal = createReadySignal();
const wait = jest.fn(() => readySignal.wait());
const signal = jest.fn((value) => readySignal.signal(value));
const isEmitted = jest.fn(() => readySignal.isEmitted());
const createReadySignalMock = jest.fn(() => ({ wait, signal, isEmitted }));
mockCreateReadySignal.mockReset();
mockCreateReadySignal.mockImplementation(createReadySignalMock);
const context = createEsContext({
logger,
indexNameRoot: 'test2',
kibanaVersion: '1.2.3',
elasticsearchClientPromise: Promise.resolve(elasticsearchClient),
});
expect(mockCreateReadySignal).toBeCalledTimes(1);
elasticsearchClient.indices.existsTemplate.mockResponse(true);
expect(signal).toBeCalledTimes(0);
context.initialize();
await context.shutdown();
expect(signal).toBeCalledTimes(1);
expect(signal).toBeCalledWith(false);
});
test('should handled failed initialization', async () => {
jest.requireMock('./init').initializeEs.mockResolvedValue(false);
const context = createEsContext({

View file

@ -70,13 +70,17 @@ class EsContextImpl implements EsContext {
this.logger.debug(`readySignal.signal(${success})`);
this.readySignal.signal(success);
} catch (err) {
this.logger.debug('readySignal.signal(false)');
this.logger.debug(`readySignal.signal(false), reason: ${err.message}`);
this.readySignal.signal(false);
}
});
}
async shutdown() {
if (!this.readySignal.isEmitted()) {
this.logger.debug('readySignal.signal(false); reason: Kibana server is shutting down');
this.readySignal.signal(false);
}
await this.esAdapter.shutdown();
}

View file

@ -15,8 +15,11 @@ describe('ReadySignal', () => {
});
test('works as expected', async () => {
expect(readySignal.isEmitted()).toEqual(false);
readySignal.signal(42);
expect(readySignal.isEmitted()).toEqual(true);
const ready = await readySignal.wait();
expect(ready).toBe(42);
expect(readySignal.isEmitted()).toEqual(true);
});
});

View file

@ -8,10 +8,12 @@
export interface ReadySignal<T = void> {
wait(): Promise<T>;
signal(value: T): void;
isEmitted(): boolean;
}
export function createReadySignal<T>(): ReadySignal<T> {
let resolver: (value: T) => void;
let emitted: boolean = false;
const promise = new Promise<T>((resolve) => {
resolver = resolve;
@ -22,8 +24,13 @@ export function createReadySignal<T>(): ReadySignal<T> {
}
function signal(value: T) {
emitted = true;
resolver(value);
}
return { wait, signal };
function isEmitted(): boolean {
return emitted;
}
return { wait, signal, isEmitted };
}