UNPKG

@backstage/backend-app-api

Version:

Core API used by Backstage backend apps

131 lines (128 loc) 4.41 kB
'use strict'; const LOGGER_INTERVAL_MAX = 6e4; function joinIds(ids) { return [...ids].map((id) => `'${id}'`).join(", "); } function createInitializationResultCollector(options) { const logger = options.logger?.child({ type: "initialization" }); const beginAt = /* @__PURE__ */ new Date(); const starting = new Set(options.pluginIds.toSorted()); const started = /* @__PURE__ */ new Set(); let hasDisallowedFailures = false; const pluginResults = []; const moduleResultsByPlugin = new Map( Array.from(starting).map((pluginId) => [pluginId, []]) ); logger?.info(`Plugin initialization started: ${joinIds(starting)}`); const getInitStatus = () => { let status = ""; if (started.size > 0) { status = `, newly initialized: ${joinIds(started)}`; started.clear(); } if (starting.size > 0) { status += `, still initializing: ${joinIds(starting)}`; } return status; }; let interval = 1e3; let prevInterval = 0; let timeout; const onTimeout = () => { logger?.info(`Plugin initialization in progress${getInitStatus()}`); const nextInterval = Math.min(interval + prevInterval, LOGGER_INTERVAL_MAX); prevInterval = interval; interval = nextInterval; timeout = setTimeout(onTimeout, nextInterval); }; timeout = setTimeout(onTimeout, interval); return { onPluginResult(pluginId, error) { starting.delete(pluginId); started.add(pluginId); const modules = moduleResultsByPlugin.get(pluginId); if (!modules) { throw new Error( `Failed to push plugin result for nonexistent plugin '${pluginId}'` ); } if (!error) { pluginResults.push({ pluginId, resultAt: /* @__PURE__ */ new Date(), modules }); } else { const allowed = options.allowBootFailurePredicate(pluginId); pluginResults.push({ pluginId, resultAt: /* @__PURE__ */ new Date(), modules, failure: { error, allowed } }); if (allowed) { logger?.error( `Plugin '${pluginId}' threw an error during startup, but boot failure is permitted for this plugin so startup will continue.`, error ); } else { hasDisallowedFailures = true; const status = starting.size > 0 ? `, waiting for ${starting.size} other plugins to finish before shutting down the process` : ""; logger?.error( `Plugin '${pluginId}' threw an error during startup${status}.`, error ); } } }, onPluginModuleResult(pluginId, moduleId, error) { const moduleResults = moduleResultsByPlugin.get(pluginId); if (!moduleResults) { throw new Error( `Failed to push module result for nonexistent plugin '${pluginId}'` ); } if (!error) { moduleResults.push({ moduleId, resultAt: /* @__PURE__ */ new Date() }); } else { const allowed = options.allowBootFailurePredicate(pluginId, moduleId); moduleResults.push({ moduleId, resultAt: /* @__PURE__ */ new Date(), failure: { error, allowed } }); if (allowed) { logger?.error( `Module ${moduleId} in Plugin '${pluginId}' threw an error during startup, but boot failure is permitted for this plugin module so startup will continue.`, error ); } else { hasDisallowedFailures = true; const status = starting.size > 0 ? `, waiting for ${starting.size} other plugins to finish before shutting down the process` : ""; logger?.error( `Module ${moduleId} in Plugin '${pluginId}' threw an error during startup${status}.`, error ); } } }, finalize() { logger?.info(`Plugin initialization complete${getInitStatus()}`); if (timeout) { clearTimeout(timeout); timeout = void 0; } return { beginAt, resultAt: /* @__PURE__ */ new Date(), outcome: hasDisallowedFailures ? "failure" : "success", plugins: pluginResults }; } }; } exports.createInitializationResultCollector = createInitializationResultCollector; //# sourceMappingURL=createInitializationResultCollector.cjs.js.map