diff --git a/.changeset/tiny-oranges-thank.md b/.changeset/tiny-oranges-thank.md new file mode 100644 index 0000000000..179aeea1c4 --- /dev/null +++ b/.changeset/tiny-oranges-thank.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-tech-insights-backend': patch +--- + +Modify Tech insight initialization to expose FactRetrieverEngine. Enables users to trigger fact retrieval manually or reschedule retrievers on runtime. diff --git a/plugins/tech-insights-backend/api-report.md b/plugins/tech-insights-backend/api-report.md index dc90d76107..b7de961034 100644 --- a/plugins/tech-insights-backend/api-report.md +++ b/plugins/tech-insights-backend/api-report.md @@ -45,6 +45,13 @@ export const entityMetadataFactRetriever: FactRetriever; // @public export const entityOwnershipFactRetriever: FactRetriever; +// @public +export interface FactRetrieverEngine { + getJobRegistration(ref: string): Promise; + schedule(): Promise; + triggerJob(ref: string): Promise; +} + // @public (undocumented) export type FactRetrieverRegistrationOptions = { cadence: string; @@ -92,6 +99,7 @@ export type TechInsightsContext< > = { factChecker?: FactChecker; persistenceContext: PersistenceContext; + factRetrieverEngine: FactRetrieverEngine; }; // @public (undocumented) diff --git a/plugins/tech-insights-backend/src/index.ts b/plugins/tech-insights-backend/src/index.ts index 66180b1006..28a922cd67 100644 --- a/plugins/tech-insights-backend/src/index.ts +++ b/plugins/tech-insights-backend/src/index.ts @@ -22,7 +22,7 @@ export type { TechInsightsOptions, TechInsightsContext, } from './service/techInsightsContextBuilder'; - +export type { FactRetrieverEngine } from './service/fact/FactRetrieverEngine'; export type { PersistenceContext } from './service/persistence/persistenceContext'; export { createFactRetrieverRegistration } from './service/fact/createFactRetriever'; export type { FactRetrieverRegistry } from './service/fact/FactRetrieverRegistry'; 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 131635a1de..3a9506ed46 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.test.ts @@ -21,7 +21,10 @@ import { TechInsightsStore, } from '@backstage/plugin-tech-insights-node'; import { FactRetrieverRegistry } from './FactRetrieverRegistry'; -import { FactRetrieverEngine } from './FactRetrieverEngine'; +import { + DefaultFactRetrieverEngine, + FactRetrieverEngine, +} from './FactRetrieverEngine'; import { DatabaseManager, getVoidLogger, @@ -131,7 +134,7 @@ describe('FactRetrieverEngine', () => { }; const manager = databaseManager as DatabaseManager; const scheduler = new TaskScheduler(manager, getVoidLogger()); - return await FactRetrieverEngine.create({ + return await DefaultFactRetrieverEngine.create({ factRetrieverContext: { logger: getVoidLogger(), config: ConfigReader.fromConfigs([]), diff --git a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts index f8ff3762dd..2d738b7de8 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverEngine.ts @@ -38,7 +38,36 @@ function duration(startTimestamp: [number, number]): string { return `${seconds.toFixed(1)}s`; } -export class FactRetrieverEngine { +/** + * @public + * + * FactRetrieverEngine responsible scheduling and running fact retrieval tasks. + */ +export interface FactRetrieverEngine { + /** + * Schedules fact retriever run cycles based on configuration provided in the registration. + * + * Default implementation uses backend-tasks to handle scheduling. This function can be called multiple + * times, where initial calls schedule the tasks and subsequents invocations update the schedules. + */ + schedule(): Promise; + + /** + * Provides possibility to manually run a fact retriever job and construct fact data + * + * @param ref - Reference to the task name stored in the executor database. By convention this is the fact retriever id + */ + triggerJob(ref: string): Promise; + + /** + * Exposes fact retriever job configuration information about previous and next runs and schedule + * + * @param ref - Reference to the task name stored in the executor database. By convention this is the fact retriever id + */ + getJobRegistration(ref: string): Promise; +} + +export class DefaultFactRetrieverEngine implements FactRetrieverEngine { private constructor( private readonly repository: TechInsightsStore, private readonly factRetrieverRegistry: FactRetrieverRegistry, @@ -69,7 +98,7 @@ export class FactRetrieverEngine { const retrievers = await factRetrieverRegistry.listRetrievers(); await Promise.all(retrievers.map(it => repository.insertFactSchema(it))); - return new FactRetrieverEngine( + return new DefaultFactRetrieverEngine( repository, factRetrieverRegistry, factRetrieverContext, diff --git a/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts b/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts index 9f4be11bec..62adbad8e3 100644 --- a/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts +++ b/plugins/tech-insights-backend/src/service/fact/FactRetrieverRegistry.ts @@ -36,7 +36,7 @@ export interface FactRetrieverRegistry { /** * A basic in memory fact retriever registry. * - * You can replace this with a persistance based version using the FactRetrieverRegistry interface. + * You can replace this with a persistence based version using the FactRetrieverRegistry interface. * */ export class DefaultFactRetrieverRegistry implements FactRetrieverRegistry { diff --git a/plugins/tech-insights-backend/src/service/router.ts b/plugins/tech-insights-backend/src/service/router.ts index b86677ab90..4b93bf4d60 100644 --- a/plugins/tech-insights-backend/src/service/router.ts +++ b/plugins/tech-insights-backend/src/service/router.ts @@ -142,7 +142,7 @@ export async function createRouter< }); /** - * /facts/latest?entity=component:default/mycomponent&startDateTime=2021-12-24T01:23:45&endDateTime=2021-12-31T23:59:59&ids[]=factRetrieverId1&ids[]=factRetrieverId2 + * /facts/range?entity=component:default/mycomponent&startDateTime=2021-12-24T01:23:45&endDateTime=2021-12-31T23:59:59&ids[]=factRetrieverId1&ids[]=factRetrieverId2 */ router.get('/facts/range', async (req, res) => { const { entity } = req.query; diff --git a/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.test.ts b/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.test.ts index 82f504c8a8..7a274e6f96 100644 --- a/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.test.ts +++ b/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.test.ts @@ -27,7 +27,7 @@ import { Knex } from 'knex'; jest.mock('./fact/FactRetrieverRegistry'); jest.mock('./fact/FactRetrieverEngine', () => ({ - FactRetrieverEngine: { + DefaultFactRetrieverEngine: { create: jest.fn().mockResolvedValue({ schedule: jest.fn(), }), diff --git a/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts b/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts index 9c54036020..f85d99b2a8 100644 --- a/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts +++ b/plugins/tech-insights-backend/src/service/techInsightsContextBuilder.ts @@ -14,7 +14,10 @@ * limitations under the License. */ -import { FactRetrieverEngine } from './fact/FactRetrieverEngine'; +import { + DefaultFactRetrieverEngine, + FactRetrieverEngine, +} from './fact/FactRetrieverEngine'; import { Logger } from 'winston'; import { DefaultFactRetrieverRegistry, @@ -93,6 +96,7 @@ export type TechInsightsContext< > = { factChecker?: FactChecker; persistenceContext: PersistenceContext; + factRetrieverEngine: FactRetrieverEngine; }; /** @@ -139,7 +143,7 @@ export const buildTechInsightsContext = async < logger, }); - const factRetrieverEngine = await FactRetrieverEngine.create({ + const factRetrieverEngine = await DefaultFactRetrieverEngine.create({ scheduler, repository: persistenceContext.techInsightsStore, factRetrieverRegistry, @@ -160,10 +164,12 @@ export const buildTechInsightsContext = async < return { persistenceContext, factChecker, + factRetrieverEngine, }; } return { persistenceContext, + factRetrieverEngine, }; };