@backstage/backend-app-api
Version:
Core API used by Backstage backend apps
131 lines (128 loc) • 4.41 kB
JavaScript
;
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