[7.x] [new-platform] Add lifecycle hooks to legacy platform (#36047) (#36124)

This commit is contained in:
Josh Dover 2019-05-06 14:22:44 -05:00 committed by GitHub
parent d97c59e883
commit 69f562ce14
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 222 additions and 3 deletions

View file

@ -16,4 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
export { __newPlatformSetup__, __newPlatformStart__, getNewPlatform } from './new_platform';
export {
__newPlatformSetup__,
__newPlatformStart__,
getNewPlatform,
onSetup,
onStart,
} from './new_platform';

View file

@ -0,0 +1,146 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import {
__newPlatformSetup__,
__newPlatformStart__,
__reset__,
onSetup,
onStart,
} from './new_platform';
describe('onSetup', () => {
afterEach(() => __reset__());
it('resolves callbacks registered before setup', async () => {
const aCallback = jest.fn(() => 1);
const bCallback = jest.fn(() => 2);
const a = onSetup(aCallback);
const b = onSetup(bCallback);
const coreSetup = { fake: true } as any;
__newPlatformSetup__(coreSetup);
expect(await Promise.all([a, b])).toEqual([1, 2]);
expect(aCallback).toHaveBeenCalledWith({ core: { fake: true }, plugins: {} });
expect(bCallback).toHaveBeenCalledWith({ core: { fake: true }, plugins: {} });
});
it('resolves callbacks registered after setup', async () => {
const callback = jest.fn(() => 3);
const coreSetup = { fake: true } as any;
__newPlatformSetup__(coreSetup);
expect(await onSetup(callback)).toEqual(3);
expect(callback).toHaveBeenCalledWith({ core: { fake: true }, plugins: {} });
});
it('rejects errors in callbacks registered before setup', async () => {
const aCallback = jest.fn(() => {
throw new Error('a error!');
});
const bCallback = jest.fn(() => {
throw new Error('b error!');
});
const cCallback = jest.fn(() => 3);
const a = onSetup(aCallback);
const b = onSetup(bCallback);
const c = onSetup(cCallback);
const coreSetup = { fake: true } as any;
__newPlatformSetup__(coreSetup);
await expect(a).rejects.toThrowError('a error!');
await expect(b).rejects.toThrowError('b error!');
// make sure one exception doesn't stop other callbacks from running
await expect(c).resolves.toEqual(3);
});
it('rejects errors in callbacks registered after setup', async () => {
const callback = jest.fn(() => {
throw new Error('a error!');
});
const coreSetup = { fake: true } as any;
__newPlatformSetup__(coreSetup);
await expect(onSetup(callback)).rejects.toThrowError('a error!');
});
});
describe('onStart', () => {
afterEach(() => __reset__());
it('resolves callbacks registered before start', async () => {
const aCallback = jest.fn(() => 1);
const bCallback = jest.fn(() => 2);
const a = onStart(aCallback);
const b = onStart(bCallback);
const coreStart = { fake: true } as any;
__newPlatformStart__(coreStart);
expect(await Promise.all([a, b])).toEqual([1, 2]);
expect(aCallback).toHaveBeenCalledWith({ core: { fake: true }, plugins: {} });
expect(bCallback).toHaveBeenCalledWith({ core: { fake: true }, plugins: {} });
});
it('resolves callbacks registered after start', async () => {
const callback = jest.fn(() => 3);
const coreStart = { fake: true } as any;
__newPlatformStart__(coreStart);
expect(await onStart(callback)).toEqual(3);
expect(callback).toHaveBeenCalledWith({ core: { fake: true }, plugins: {} });
});
it('rejects errors in callbacks registered before start', async () => {
const aCallback = jest.fn(() => {
throw new Error('a error!');
});
const bCallback = jest.fn(() => {
throw new Error('b error!');
});
const cCallback = jest.fn(() => 3);
const a = onStart(aCallback);
const b = onStart(bCallback);
const c = onStart(cCallback);
const coreStart = { fake: true } as any;
__newPlatformStart__(coreStart);
await expect(a).rejects.toThrowError('a error!');
await expect(b).rejects.toThrowError('b error!');
// make sure one exception doesn't stop other callbacks from running
await expect(c).resolves.toEqual(3);
});
it('rejects errors in callbacks registered after start', async () => {
const callback = jest.fn(() => {
throw new Error('a error!');
});
const coreStart = { fake: true } as any;
__newPlatformStart__(coreStart);
await expect(onStart(callback)).rejects.toThrowError('a error!');
});
});

View file

@ -29,20 +29,41 @@ const runtimeContext = {
},
};
export function __newPlatformSetup__(core: CoreSetup) {
/**
* Only used by unit tests
* @internal
*/
export function __reset__() {
runtimeContext.setup.core = (null as unknown) as CoreSetup;
runtimeContext.start.core = (null as unknown) as CoreStart;
}
export async function __newPlatformSetup__(core: CoreSetup) {
if (runtimeContext.setup.core) {
throw new Error('New platform core api was already set up');
}
runtimeContext.setup.core = core;
// Process any pending onSetup callbacks
while (onSetupCallbacks.length) {
const cb = onSetupCallbacks.shift()!;
await cb(runtimeContext.setup);
}
}
export function __newPlatformStart__(core: CoreStart) {
export async function __newPlatformStart__(core: CoreStart) {
if (runtimeContext.start.core) {
throw new Error('New platform core api was already started');
}
runtimeContext.start.core = core;
// Process any pending onStart callbacks
while (onStartCallbacks.length) {
const cb = onStartCallbacks.shift()!;
await cb(runtimeContext.start);
}
}
export function getNewPlatform() {
@ -52,3 +73,49 @@ export function getNewPlatform() {
return runtimeContext;
}
type SetupCallback<T> = (startContext: typeof runtimeContext['setup']) => T;
type StartCallback<T> = (startContext: typeof runtimeContext['start']) => T;
const onSetupCallbacks: Array<SetupCallback<Promise<unknown>>> = [];
const onStartCallbacks: Array<StartCallback<Promise<unknown>>> = [];
/**
* Register a callback to be called once the new platform is in the
* `setup` lifecycle event. Resolves to the return value of the callback.
*/
export async function onSetup<T>(callback: SetupCallback<T>): Promise<T> {
if (runtimeContext.setup.core !== null) {
return callback(runtimeContext.setup);
}
return new Promise((resolve, reject) => {
onSetupCallbacks.push(async (setupContext: typeof runtimeContext['setup']) => {
try {
resolve(await callback(setupContext));
} catch (e) {
reject(e);
}
});
});
}
/**
* Register a callback to be called once the new platform is in the
* `start` lifecycle event. Resolves to the return value of the callback.
*/
export async function onStart<T>(callback: StartCallback<T>): Promise<T> {
if (runtimeContext.start.core !== null) {
return callback(runtimeContext.start);
}
return new Promise((resolve, reject) => {
onStartCallbacks.push(async (startContext: typeof runtimeContext['start']) => {
try {
resolve(await callback(startContext));
} catch (e) {
reject(e);
}
});
});
}