Merge pull request #12325 from sblausten/tech-insights-context
Allow FactRetrieverRegistry to be injected into builder for flexibility
This commit is contained in:
@@ -11,6 +11,7 @@ import { FactCheckerFactory } from '@backstage/plugin-tech-insights-node';
|
||||
import { FactLifecycle } from '@backstage/plugin-tech-insights-node';
|
||||
import { FactRetriever } from '@backstage/plugin-tech-insights-node';
|
||||
import { FactRetrieverRegistration } from '@backstage/plugin-tech-insights-node';
|
||||
import { FactSchema } from '@backstage/plugin-tech-insights-node';
|
||||
import { Logger } from 'winston';
|
||||
import { PluginDatabaseManager } from '@backstage/backend-common';
|
||||
import { PluginEndpointDiscovery } from '@backstage/backend-common';
|
||||
@@ -51,6 +52,22 @@ export type FactRetrieverRegistrationOptions = {
|
||||
lifecycle?: FactLifecycle;
|
||||
};
|
||||
|
||||
// @public (undocumented)
|
||||
export interface FactRetrieverRegistry {
|
||||
// (undocumented)
|
||||
get(retrieverReference: string): FactRetrieverRegistration;
|
||||
// (undocumented)
|
||||
getSchemas(): FactSchema[];
|
||||
// (undocumented)
|
||||
listRegistrations(): FactRetrieverRegistration[];
|
||||
// (undocumented)
|
||||
listRetrievers(): FactRetriever[];
|
||||
// (undocumented)
|
||||
register(registration: FactRetrieverRegistration): void;
|
||||
// (undocumented)
|
||||
readonly retrievers: Map<string, FactRetrieverRegistration>;
|
||||
}
|
||||
|
||||
// @public
|
||||
export type PersistenceContext = {
|
||||
techInsightsStore: TechInsightsStore;
|
||||
@@ -91,7 +108,8 @@ export interface TechInsightsOptions<
|
||||
// (undocumented)
|
||||
discovery: PluginEndpointDiscovery;
|
||||
factCheckerFactory?: FactCheckerFactory<CheckType, CheckResultType>;
|
||||
factRetrievers: FactRetrieverRegistration[];
|
||||
factRetrieverRegistry?: FactRetrieverRegistry;
|
||||
factRetrievers?: FactRetrieverRegistration[];
|
||||
// (undocumented)
|
||||
logger: Logger;
|
||||
// (undocumented)
|
||||
|
||||
@@ -25,5 +25,6 @@ export type {
|
||||
|
||||
export type { PersistenceContext } from './service/persistence/persistenceContext';
|
||||
export { createFactRetrieverRegistration } from './service/fact/createFactRetriever';
|
||||
export type { FactRetrieverRegistry } from './service/fact/FactRetrieverRegistry';
|
||||
export type { FactRetrieverRegistrationOptions } from './service/fact/createFactRetriever';
|
||||
export * from './service/fact/factRetrievers';
|
||||
|
||||
@@ -21,8 +21,21 @@ import {
|
||||
} from '@backstage/plugin-tech-insights-node';
|
||||
import { ConflictError, NotFoundError } from '@backstage/errors';
|
||||
|
||||
export class FactRetrieverRegistry {
|
||||
private readonly retrievers = new Map<string, FactRetrieverRegistration>();
|
||||
/**
|
||||
* @public
|
||||
*
|
||||
*/
|
||||
export interface FactRetrieverRegistry {
|
||||
readonly retrievers: Map<string, FactRetrieverRegistration>;
|
||||
register(registration: FactRetrieverRegistration): void;
|
||||
get(retrieverReference: string): FactRetrieverRegistration;
|
||||
listRetrievers(): FactRetriever[];
|
||||
listRegistrations(): FactRetrieverRegistration[];
|
||||
getSchemas(): FactSchema[];
|
||||
}
|
||||
|
||||
export class DefaultFactRetrieverRegistry implements FactRetrieverRegistry {
|
||||
readonly retrievers = new Map<string, FactRetrieverRegistration>();
|
||||
|
||||
constructor(retrievers: FactRetrieverRegistration[]) {
|
||||
retrievers.forEach(it => {
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { buildTechInsightsContext } from './techInsightsContextBuilder';
|
||||
import {
|
||||
DatabaseManager,
|
||||
getVoidLogger,
|
||||
PluginDatabaseManager,
|
||||
ServerTokenManager,
|
||||
} from '@backstage/backend-common';
|
||||
import { ConfigReader } from '@backstage/config';
|
||||
import { TaskScheduler } from '@backstage/backend-tasks';
|
||||
import { DefaultFactRetrieverRegistry } from './fact/FactRetrieverRegistry';
|
||||
import { Knex } from 'knex';
|
||||
|
||||
jest.mock('./fact/FactRetrieverRegistry');
|
||||
jest.mock('./fact/FactRetrieverEngine', () => ({
|
||||
FactRetrieverEngine: {
|
||||
create: jest.fn().mockResolvedValue({
|
||||
schedule: jest.fn(),
|
||||
}),
|
||||
},
|
||||
}));
|
||||
|
||||
describe('buildTechInsightsContext', () => {
|
||||
const pluginDatabase: PluginDatabaseManager = {
|
||||
getClient: () => {
|
||||
return Promise.resolve({
|
||||
migrate: {
|
||||
latest: () => {},
|
||||
},
|
||||
}) as unknown as Promise<Knex>;
|
||||
},
|
||||
};
|
||||
const databaseManager: Partial<DatabaseManager> = {
|
||||
forPlugin: () => pluginDatabase,
|
||||
};
|
||||
const manager = databaseManager as DatabaseManager;
|
||||
const discoveryMock = {
|
||||
getBaseUrl: (_: string) => Promise.resolve('http://mock.url'),
|
||||
getExternalBaseUrl: (_: string) => Promise.resolve('http://mock.url'),
|
||||
};
|
||||
const scheduler = new TaskScheduler(manager, getVoidLogger()).forPlugin(
|
||||
'tech-insights',
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('constructs the default FactRetrieverRegistry if factRetrievers but no factRetrieverRegistry are passed', () => {
|
||||
buildTechInsightsContext({
|
||||
database: pluginDatabase,
|
||||
logger: getVoidLogger(),
|
||||
factRetrievers: [],
|
||||
scheduler: scheduler,
|
||||
config: ConfigReader.fromConfigs([]),
|
||||
discovery: discoveryMock,
|
||||
tokenManager: ServerTokenManager.noop(),
|
||||
});
|
||||
expect(DefaultFactRetrieverRegistry).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('uses factRetrieverRegistry implementation instead of the default FactRetrieverRegistry if it is passed in', () => {
|
||||
const factRetrieverRegistryMock = {} as DefaultFactRetrieverRegistry;
|
||||
|
||||
buildTechInsightsContext({
|
||||
database: pluginDatabase,
|
||||
logger: getVoidLogger(),
|
||||
factRetrievers: [],
|
||||
factRetrieverRegistry: factRetrieverRegistryMock,
|
||||
scheduler: scheduler,
|
||||
config: ConfigReader.fromConfigs([]),
|
||||
discovery: discoveryMock,
|
||||
tokenManager: ServerTokenManager.noop(),
|
||||
});
|
||||
expect(DefaultFactRetrieverRegistry).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
import { FactRetrieverEngine } from './fact/FactRetrieverEngine';
|
||||
import { Logger } from 'winston';
|
||||
import { FactRetrieverRegistry } from './fact/FactRetrieverRegistry';
|
||||
import {
|
||||
DefaultFactRetrieverRegistry,
|
||||
FactRetrieverRegistry,
|
||||
} from './fact/FactRetrieverRegistry';
|
||||
import { Config } from '@backstage/config';
|
||||
import {
|
||||
PluginDatabaseManager,
|
||||
@@ -49,16 +52,25 @@ export interface TechInsightsOptions<
|
||||
CheckResultType extends CheckResult,
|
||||
> {
|
||||
/**
|
||||
* A collection of FactRetrieverRegistrations.
|
||||
* Optional collection of FactRetrieverRegistrations (required if no factRetrieverRegistry passed in).
|
||||
* Used to register FactRetrievers and their schemas and schedule an execution loop for them.
|
||||
*
|
||||
* Not needed if passing in your own FactRetrieverRegistry implementation. Required otherwise.
|
||||
*/
|
||||
factRetrievers: FactRetrieverRegistration[];
|
||||
factRetrievers?: FactRetrieverRegistration[];
|
||||
|
||||
/**
|
||||
* Optional factory exposing a `construct` method to initialize a FactChecker implementation
|
||||
*/
|
||||
factCheckerFactory?: FactCheckerFactory<CheckType, CheckResultType>;
|
||||
|
||||
/**
|
||||
* Optional FactRetrieverRegistry implementation that replaces the default one.
|
||||
*
|
||||
* If passing this in you don't need to pass in factRetrievers also.
|
||||
*/
|
||||
factRetrieverRegistry?: FactRetrieverRegistry;
|
||||
|
||||
logger: Logger;
|
||||
config: Config;
|
||||
discovery: PluginEndpointDiscovery;
|
||||
@@ -109,7 +121,19 @@ export const buildTechInsightsContext = async <
|
||||
tokenManager,
|
||||
} = options;
|
||||
|
||||
const factRetrieverRegistry = new FactRetrieverRegistry(factRetrievers);
|
||||
const buildFactRetrieverRegistry = (): FactRetrieverRegistry => {
|
||||
if (!options.factRetrieverRegistry) {
|
||||
if (!factRetrievers) {
|
||||
throw new Error(
|
||||
'Failed to build FactRetrieverRegistry because no factRetrievers found',
|
||||
);
|
||||
}
|
||||
return new DefaultFactRetrieverRegistry(factRetrievers);
|
||||
}
|
||||
return options.factRetrieverRegistry;
|
||||
};
|
||||
|
||||
const factRetrieverRegistry = buildFactRetrieverRegistry();
|
||||
|
||||
const persistenceContext = await initializePersistenceContext(
|
||||
await database.getClient(),
|
||||
|
||||
Reference in New Issue
Block a user