diff --git a/.changeset/rich-goats-breathe.md b/.changeset/rich-goats-breathe.md new file mode 100644 index 0000000000..2888c2f9a7 --- /dev/null +++ b/.changeset/rich-goats-breathe.md @@ -0,0 +1,7 @@ +--- +'@backstage/plugin-tech-insights-backend': minor +--- + +**BREAKING**: Update FactRetrieverRegistry interface to be async so that db backed implementations can be passed through to the FactRetrieverEngine. + +If you have existing custom `FactRetrieverRegistry` implementations, you'll need to remove the `retrievers` member and make all the methods async. diff --git a/plugins/tech-insights-backend/api-report.md b/plugins/tech-insights-backend/api-report.md index 32d45f8afd..dc90d76107 100644 --- a/plugins/tech-insights-backend/api-report.md +++ b/plugins/tech-insights-backend/api-report.md @@ -55,17 +55,15 @@ export type FactRetrieverRegistrationOptions = { // @public (undocumented) export interface FactRetrieverRegistry { // (undocumented) - get(retrieverReference: string): FactRetrieverRegistration; + get(retrieverReference: string): Promise; // (undocumented) - getSchemas(): FactSchema[]; + getSchemas(): Promise; // (undocumented) - listRegistrations(): FactRetrieverRegistration[]; + listRegistrations(): Promise; // (undocumented) - listRetrievers(): FactRetriever[]; + listRetrievers(): Promise; // (undocumented) - register(registration: FactRetrieverRegistration): void; - // (undocumented) - readonly retrievers: Map; + register(registration: FactRetrieverRegistration): Promise; } // @public diff --git a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts index 454711171f..44ffa6587f 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts @@ -206,9 +206,7 @@ describe('FactRetrieverEngine', () => { { ...testFactRetriever, handler }, ); await engine.schedule(); - const job: FactRetrieverRegistration = engine.getJobRegistration( - testFactRetriever.id, - ); + const job = await engine.getJobRegistration(testFactRetriever.id); expect(job.cadence!!).toEqual(defaultCadence); await engine.triggerJob(job.factRetriever.id); diff --git a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts index 25e7610809..f8ff3762dd 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts @@ -66,11 +66,8 @@ export class FactRetrieverEngine { defaultTimeout, } = options; - await Promise.all( - factRetrieverRegistry - .listRetrievers() - .map(it => repository.insertFactSchema(it)), - ); + const retrievers = await factRetrieverRegistry.listRetrievers(); + await Promise.all(retrievers.map(it => repository.insertFactSchema(it))); return new FactRetrieverEngine( repository, @@ -84,7 +81,7 @@ export class FactRetrieverEngine { } async schedule() { - const registrations = this.factRetrieverRegistry.listRegistrations(); + const registrations = await this.factRetrieverRegistry.listRegistrations(); const newRegs: string[] = []; await Promise.all( @@ -115,7 +112,7 @@ export class FactRetrieverEngine { ); } - getJobRegistration(ref: string): FactRetrieverRegistration { + getJobRegistration(ref: string): Promise { return this.factRetrieverRegistry.get(ref); } diff --git a/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts b/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts index 504d561f17..9f4be11bec 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts @@ -26,24 +26,29 @@ import { ConflictError, NotFoundError } from '@backstage/errors'; * */ export interface FactRetrieverRegistry { - readonly retrievers: Map; - register(registration: FactRetrieverRegistration): void; - get(retrieverReference: string): FactRetrieverRegistration; - listRetrievers(): FactRetriever[]; - listRegistrations(): FactRetrieverRegistration[]; - getSchemas(): FactSchema[]; + register(registration: FactRetrieverRegistration): Promise; + get(retrieverReference: string): Promise; + listRetrievers(): Promise; + listRegistrations(): Promise; + getSchemas(): Promise; } +/** + * A basic in memory fact retriever registry. + * + * You can replace this with a persistance based version using the FactRetrieverRegistry interface. + * + */ export class DefaultFactRetrieverRegistry implements FactRetrieverRegistry { - readonly retrievers = new Map(); + private readonly retrievers = new Map(); constructor(retrievers: FactRetrieverRegistration[]) { - retrievers.forEach(it => { - this.register(it); + retrievers.forEach(r => { + this.registerSync(r); }); } - register(registration: FactRetrieverRegistration) { + registerSync(registration: FactRetrieverRegistration) { if (this.retrievers.has(registration.factRetriever.id)) { throw new ConflictError( `Tech insight fact retriever with identifier '${registration.factRetriever.id}' has already been registered`, @@ -52,7 +57,11 @@ export class DefaultFactRetrieverRegistry implements FactRetrieverRegistry { this.retrievers.set(registration.factRetriever.id, registration); } - get(retrieverReference: string): FactRetrieverRegistration { + async register(registration: FactRetrieverRegistration) { + this.registerSync(registration); + } + + async get(retrieverReference: string): Promise { const registration = this.retrievers.get(retrieverReference); if (!registration) { throw new NotFoundError( @@ -62,15 +71,16 @@ export class DefaultFactRetrieverRegistry implements FactRetrieverRegistry { return registration; } - listRetrievers(): FactRetriever[] { + async listRetrievers(): Promise { return [...this.retrievers.values()].map(it => it.factRetriever); } - listRegistrations(): FactRetrieverRegistration[] { + async listRegistrations(): Promise { return [...this.retrievers.values()]; } - getSchemas(): FactSchema[] { - return this.listRetrievers().map(it => it.schema); + async getSchemas(): Promise { + const retrievers = await this.listRetrievers(); + return retrievers.map(it => it.schema); } }