optional -> onPluginBootFailure
Signed-off-by: Tim Hansen <timbonicush@spotify.com>
This commit is contained in:
@@ -560,13 +560,15 @@ describe('BackendInitializer', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should permit startup errors for plugins marked as optional', async () => {
|
||||
it('should permit startup errors for plugins with onPluginBootFailure: continue', async () => {
|
||||
const init = new BackendInitializer([
|
||||
mockServices.rootLifecycle.factory(),
|
||||
mockServices.rootLogger.factory(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: {
|
||||
backend: { startup: { plugins: { test: { optional: true } } } },
|
||||
backend: {
|
||||
startup: { plugins: { test: { onPluginBootFailure: 'continue' } } },
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
@@ -586,12 +588,16 @@ describe('BackendInitializer', () => {
|
||||
await expect(init.start()).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
it('should permit startup errors if the default is set', async () => {
|
||||
it('should permit startup errors if the default onPluginBootFailure is continue', async () => {
|
||||
const init = new BackendInitializer([
|
||||
mockServices.rootLifecycle.factory(),
|
||||
mockServices.rootLogger.factory(),
|
||||
mockServices.rootConfig.factory({
|
||||
data: { backend: { startup: { default: { optional: true } } } },
|
||||
data: {
|
||||
backend: {
|
||||
startup: { default: { onPluginBootFailure: 'continue' } },
|
||||
},
|
||||
},
|
||||
}),
|
||||
]);
|
||||
init.add(
|
||||
@@ -610,7 +616,7 @@ describe('BackendInitializer', () => {
|
||||
await expect(init.start()).resolves.not.toThrow();
|
||||
});
|
||||
|
||||
it('should forward errors for plugins explicitly marked as not optional when the default is true', async () => {
|
||||
it('should forward errors for plugins explicitly marked to abort when the default is continue', async () => {
|
||||
const init = new BackendInitializer([
|
||||
mockServices.rootLifecycle.factory(),
|
||||
mockServices.rootLogger.factory(),
|
||||
@@ -618,8 +624,8 @@ describe('BackendInitializer', () => {
|
||||
data: {
|
||||
backend: {
|
||||
startup: {
|
||||
default: { optional: true },
|
||||
plugins: { test: { optional: false } },
|
||||
default: { onPluginBootFailure: 'continue' },
|
||||
plugins: { test: { onPluginBootFailure: 'abort' } },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -330,7 +330,7 @@ export class BackendInitializer {
|
||||
// All plugins are initialized in parallel
|
||||
const results = await Promise.allSettled(
|
||||
allPluginIds.map(async pluginId => {
|
||||
const isPluginOptional = this.#getPluginOptionalityPredicate(
|
||||
const isBootFailurePermitted = this.#getPluginBootFailurePredicate(
|
||||
pluginId,
|
||||
rootConfig,
|
||||
);
|
||||
@@ -403,8 +403,8 @@ export class BackendInitializer {
|
||||
await lifecycleService.startup();
|
||||
} catch (error: unknown) {
|
||||
assertError(error);
|
||||
if (isPluginOptional) {
|
||||
initLogger.onOptionalPluginFailed(pluginId, error);
|
||||
if (isBootFailurePermitted) {
|
||||
initLogger.onPermittedPluginFailure(pluginId, error);
|
||||
} else {
|
||||
initLogger.onPluginFailed(pluginId, error);
|
||||
throw error;
|
||||
@@ -636,15 +636,18 @@ export class BackendInitializer {
|
||||
}
|
||||
}
|
||||
|
||||
#getPluginOptionalityPredicate(pluginId: string, config?: Config): boolean {
|
||||
const defaultStartupOptionalValue =
|
||||
config?.getOptionalBoolean('backend.startup.default.optional') ?? false;
|
||||
#getPluginBootFailurePredicate(pluginId: string, config?: Config): boolean {
|
||||
const defaultStartupBootFailureValue =
|
||||
config?.getOptionalString(
|
||||
'backend.startup.default.onPluginBootFailure',
|
||||
) ?? 'abort';
|
||||
|
||||
return (
|
||||
config?.getOptionalBoolean(
|
||||
`backend.startup.plugins.${pluginId}.optional`,
|
||||
) ?? defaultStartupOptionalValue
|
||||
);
|
||||
const pluginStartupBootFailureValue =
|
||||
config?.getOptionalString(
|
||||
`backend.startup.plugins.${pluginId}.onPluginBootFailure`,
|
||||
) ?? defaultStartupBootFailureValue;
|
||||
|
||||
return pluginStartupBootFailureValue === 'continue';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ export function createInitializationLogger(
|
||||
): {
|
||||
onPluginStarted(pluginId: string): void;
|
||||
onPluginFailed(pluginId: string, error: Error): void;
|
||||
onOptionalPluginFailed(pluginId: string, error: Error): void;
|
||||
onPermittedPluginFailure(pluginId: string, error: Error): void;
|
||||
onAllStarted(): void;
|
||||
} {
|
||||
const logger = rootLogger?.child({ type: 'initialization' });
|
||||
@@ -80,10 +80,10 @@ export function createInitializationLogger(
|
||||
error,
|
||||
);
|
||||
},
|
||||
onOptionalPluginFailed(pluginId: string, error: Error) {
|
||||
onPermittedPluginFailure(pluginId: string, error: Error) {
|
||||
starting.delete(pluginId);
|
||||
logger?.error(
|
||||
`Plugin '${pluginId}' threw an error during startup, but the plugin is marked optional in config so startup will continue.`,
|
||||
`Plugin '${pluginId}' threw an error during startup, but boot failure is permitted for this plugin so startup will continue.`,
|
||||
error,
|
||||
);
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user