diff --git a/.changeset/tame-ads-appear.md b/.changeset/tame-ads-appear.md new file mode 100644 index 0000000000..887cc73252 --- /dev/null +++ b/.changeset/tame-ads-appear.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-tech-insights-backend': patch +'@backstage/plugin-tech-insights-node': patch +--- + +Add a default delay to the fact retrievers to prevent cold-start errors diff --git a/plugins/tech-insights-backend/api-report.md b/plugins/tech-insights-backend/api-report.md index dea5fe376c..8dc8efbb24 100644 --- a/plugins/tech-insights-backend/api-report.md +++ b/plugins/tech-insights-backend/api-report.md @@ -60,6 +60,7 @@ export type FactRetrieverRegistrationOptions = { factRetriever: FactRetriever; lifecycle?: FactLifecycle; timeout?: Duration | HumanDuration; + initialDelay?: Duration | HumanDuration; }; // @public (undocumented) diff --git a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts index 2d738b7de8..e223604829 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts @@ -76,6 +76,7 @@ export class DefaultFactRetrieverEngine implements FactRetrieverEngine { private readonly scheduler: PluginTaskScheduler, private readonly defaultCadence?: string, private readonly defaultTimeout?: Duration, + private readonly defaultInitialDelay?: Duration, ) {} static async create(options: { @@ -85,6 +86,7 @@ export class DefaultFactRetrieverEngine implements FactRetrieverEngine { scheduler: PluginTaskScheduler; defaultCadence?: string; defaultTimeout?: Duration; + defaultInitialDelay?: Duration; }) { const { repository, @@ -93,6 +95,7 @@ export class DefaultFactRetrieverEngine implements FactRetrieverEngine { scheduler, defaultCadence, defaultTimeout, + defaultInitialDelay, } = options; const retrievers = await factRetrieverRegistry.listRetrievers(); @@ -106,6 +109,7 @@ export class DefaultFactRetrieverEngine implements FactRetrieverEngine { scheduler, defaultCadence, defaultTimeout, + defaultInitialDelay, ); } @@ -115,17 +119,25 @@ export class DefaultFactRetrieverEngine implements FactRetrieverEngine { await Promise.all( registrations.map(async registration => { - const { factRetriever, cadence, lifecycle, timeout } = registration; + const { factRetriever, cadence, lifecycle, timeout, initialDelay } = + registration; const cronExpression = cadence || this.defaultCadence || randomDailyCron(); const timeLimit = timeout || this.defaultTimeout || Duration.fromObject({ minutes: 5 }); + const initialDelaySetting = + initialDelay || + this.defaultInitialDelay || + Duration.fromObject({ seconds: 5 }); try { await this.scheduler.scheduleTask({ id: factRetriever.id, frequency: { cron: cronExpression }, fn: this.createFactRetrieverHandler(factRetriever, lifecycle), timeout: timeLimit, + // We add a delay in order to prevent errors due to the + // fact that the backend is not yet online in a cold-start scenario + initialDelay: initialDelaySetting, }); newRegs.push(factRetriever.id); } catch (e) { diff --git a/plugins/tech-insights-backend/src/service/fact/createFactRetriever.ts b/plugins/tech-insights-backend/src/service/fact/createFactRetriever.ts index 6200790e6e..2d715e5e4c 100644 --- a/plugins/tech-insights-backend/src/service/fact/createFactRetriever.ts +++ b/plugins/tech-insights-backend/src/service/fact/createFactRetriever.ts @@ -36,6 +36,7 @@ export type FactRetrieverRegistrationOptions = { factRetriever: FactRetriever; lifecycle?: FactLifecycle; timeout?: Duration | HumanDuration; + initialDelay?: Duration | HumanDuration; }; /** @@ -46,6 +47,7 @@ export type FactRetrieverRegistrationOptions = { * @param factRetriever - Implementation of fact retriever consisting of at least id, version, schema and handler * @param lifecycle - Optional lifecycle definition indicating the cleanup logic of facts when this retriever is run * @param timeout - Optional duration to determine how long the fact retriever should be allowed to run, defaults to 5 minutes + * @param initialDelay - Optional initial delay to determine how long the fact retriever should wait before the initial run, defaults to 5 seconds * * * @remarks @@ -69,11 +71,12 @@ export type FactRetrieverRegistrationOptions = { export function createFactRetrieverRegistration( options: FactRetrieverRegistrationOptions, ): FactRetrieverRegistration { - const { cadence, factRetriever, lifecycle, timeout } = options; + const { cadence, factRetriever, lifecycle, timeout, initialDelay } = options; return { cadence, factRetriever, lifecycle, timeout, + initialDelay, }; } diff --git a/plugins/tech-insights-node/api-report.md b/plugins/tech-insights-node/api-report.md index 293e2fd76b..47e76b07ce 100644 --- a/plugins/tech-insights-node/api-report.md +++ b/plugins/tech-insights-node/api-report.md @@ -75,6 +75,7 @@ export type FactRetrieverRegistration = { cadence?: string; timeout?: Duration | HumanDuration; lifecycle?: FactLifecycle; + initialDelay?: Duration | HumanDuration; }; // @public diff --git a/plugins/tech-insights-node/src/facts.ts b/plugins/tech-insights-node/src/facts.ts index 2aab9ee73f..a4a0834970 100644 --- a/plugins/tech-insights-node/src/facts.ts +++ b/plugins/tech-insights-node/src/facts.ts @@ -278,4 +278,11 @@ export type FactRetrieverRegistration = { * If defined this value will be used to determine expired items which will deleted when this fact retriever is run */ lifecycle?: FactLifecycle; + + /** + * A duration to determine the initial delay for the fact retriever. Useful for cold start scenarios when e.g. the + * catalog backend is not yet available. Defaults to 5 seconds. + * + */ + initialDelay?: Duration | HumanDuration; };