optional -> onPluginBootFailure

Signed-off-by: Tim Hansen <timbonicush@spotify.com>
This commit is contained in:
Tim Hansen
2025-02-13 08:32:30 -07:00
parent 1d7a9277f4
commit 667fdb6766
5 changed files with 50 additions and 38 deletions
@@ -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,
);
},