From 57d462d5ed0f8d5e318d4a12c8e8e936fbb5a8f0 Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Thu, 16 Sep 2021 09:31:14 +0200 Subject: [PATCH] Refactor refreshes into RefreshService MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patrik Oldsberg Co-authored-by: Fredrik Adelöw Signed-off-by: Johan Haals --- .../DefaultCatalogProcessingEngine.test.ts | 242 +------------ .../next/DefaultCatalogProcessingEngine.ts | 16 - .../src/next/DefaultRefreshService.test.ts | 328 ++++++++++++++++++ .../src/next/DefaultRefreshService.ts | 46 +++ .../src/next/NextCatalogBuilder.ts | 7 +- .../catalog-backend/src/next/NextRouter.ts | 16 +- .../database/DefaultProcessingDatabase.ts | 2 +- plugins/catalog-backend/src/next/index.ts | 2 +- plugins/catalog-backend/src/next/types.ts | 24 +- plugins/catalog-backend/src/service/router.ts | 16 +- 10 files changed, 416 insertions(+), 283 deletions(-) create mode 100644 plugins/catalog-backend/src/next/DefaultRefreshService.test.ts create mode 100644 plugins/catalog-backend/src/next/DefaultRefreshService.ts diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.test.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.test.ts index a0d62c8642..f7dede4adb 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.test.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.test.ts @@ -15,27 +15,13 @@ */ import { getVoidLogger } from '@backstage/backend-common'; -import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; -import { createHash, Hash } from 'crypto'; -import { Knex } from 'knex'; -import { Logger } from 'winston'; +import { Hash } from 'crypto'; import { DateTime } from 'luxon'; -import { DatabaseManager } from './database/DatabaseManager'; import waitForExpect from 'wait-for-expect'; import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; -import { - DbRefreshStateReferencesRow, - DbRefreshStateRow, -} from './database/tables'; -import { ProcessingDatabase } from './database/types'; import { DefaultCatalogProcessingEngine } from './DefaultCatalogProcessingEngine'; -import { - CatalogProcessingOrchestrator, - EntityProcessingRequest, -} from './processing/types'; +import { CatalogProcessingOrchestrator } from './processing/types'; import { Stitcher } from './stitching/Stitcher'; -import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; -import { v4 as uuid } from 'uuid'; describe('DefaultCatalogProcessingEngine', () => { const db = { @@ -250,227 +236,3 @@ describe('DefaultCatalogProcessingEngine', () => { await engine.stop(); }); }); - -describe('DefaultCatalogProcessingEngine integration', () => { - const defaultLogger = getVoidLogger(); - const databases = TestDatabases.create({ - ids: ['POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'], - }); - - async function createDatabase( - databaseId: TestDatabaseId, - logger: Logger = defaultLogger, - ) { - const knex = await databases.init(databaseId); - await DatabaseManager.createDatabase(knex); - return { - knex, - db: new DefaultProcessingDatabase({ - database: knex, - logger, - refreshInterval: () => 100, - }), - }; - } - - const createPopulatedEngine = async (options: { - db: ProcessingDatabase; - knex: Knex; - entities: Entity[]; - references: { [source: string]: string[] }; - }) => { - const { db, knex, entities, references } = options; - - const entityMap = new Map( - entities.map(entity => [stringifyEntityRef(entity), entity]), - ); - - for (const entity of entities) { - await knex('refresh_state').insert({ - entity_id: uuid(), - entity_ref: stringifyEntityRef(entity), - unprocessed_entity: JSON.stringify(entity), - errors: '[]', - next_update_at: '2031-01-01 23:00:00', - last_discovery_at: '2021-04-01 13:37:00', - }); - } - - for (const entityRef of entityMap.keys()) { - if (!(entityRef in references)) { - await knex( - 'refresh_state_references', - ).insert({ - source_key: 'ConfigLocationProvider', - target_entity_ref: entityRef, - }); - } - } - for (const [sourceRef, targetRefs] of Object.entries(references)) { - for (const targetRef of targetRefs) { - await knex( - 'refresh_state_references', - ).insert({ - source_entity_ref: sourceRef, - target_entity_ref: targetRef, - }); - } - } - - const engine = new DefaultCatalogProcessingEngine( - defaultLogger, - [], - db, - { - async process(request: EntityProcessingRequest) { - const entityRef = stringifyEntityRef(request.entity); - const entity = entityMap.get(entityRef); - if (!entity) { - throw new Error(`Unexpected entity: ${entityRef}`); - } - const deferredEntities = - references[entityRef]?.map(ref => { - const e = entityMap.get(ref); - if (!e) { - throw new Error(`Target entity not found: ${ref}`); - } - return { entity: e, locationKey: ref }; - }) || []; - - return { - ok: true, - completedEntity: { - ...entity, - metadata: { - ...entity.metadata, - annotations: { - ...entity.metadata.annotations, - 'refresh-completed': 'true', - }, - }, - }, - relations: [], - errors: [], - deferredEntities, - state: new Map(), - }; - }, - }, - new Stitcher(knex, defaultLogger), - () => createHash('sha1'), - 50, - ); - - return engine; - }; - - const waitForRefresh = async (knex: Knex, entityRef: string) => { - for (;;) { - const [result] = await knex('refresh_state') - .where('entity_ref', entityRef) - .select(); - - const entity = result.processed_entity - ? (JSON.parse(result.processed_entity) as Entity) - : undefined; - if (entity?.metadata?.annotations?.['refresh-completed']) { - return true; - } - await new Promise(resolve => setTimeout(resolve, 500)); - } - }; - - it.each(databases.eachSupportedId())( - 'should refresh the parent location, %p', - async databaseId => { - const { knex, db } = await createDatabase(databaseId); - - const engine = await createPopulatedEngine({ - db, - knex, - entities: [ - { - kind: 'Location', - apiVersion: '1.0.0', - metadata: { - name: 'myloc', - }, - }, - { - kind: 'Component', - apiVersion: '1.0.0', - metadata: { - name: 'mycomp', - }, - }, - ], - references: { - 'location:default/myloc': ['component:default/mycomp'], - }, - }); - - await engine.start(); - - await engine.refresh({ - entityRef: 'component:default/mycomp', - }); - - await expect( - waitForRefresh(knex, 'component:default/mycomp'), - ).resolves.toBe(true); - - await engine.stop(); - }, - ); - - it.each(databases.eachSupportedId())( - 'should refresh the location further up the tree, %p', - async databaseId => { - const { knex, db } = await createDatabase(databaseId); - - const engine = await createPopulatedEngine({ - db, - knex, - entities: [ - { - kind: 'Location', - apiVersion: '1.0.0', - metadata: { - name: 'myloc', - }, - }, - { - kind: 'Component', - apiVersion: '1.0.0', - metadata: { - name: 'mycomp', - }, - }, - { - kind: 'Api', - apiVersion: '1.0.0', - metadata: { - name: 'myapi', - }, - }, - ], - references: { - 'location:default/myloc': ['component:default/mycomp'], - 'component:default/mycomp': ['api:default/myapi'], - }, - }); - - await engine.start(); - - await engine.refresh({ - entityRef: 'api:default/myapi', - }); - - await expect(waitForRefresh(knex, 'api:default/myapi')).resolves.toBe( - true, - ); - - await engine.stop(); - }, - ); -}); diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index cb3a9c6e30..4d2d74f05b 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -36,7 +36,6 @@ import { EntityProvider, EntityProviderConnection, EntityProviderMutation, - CatalogProcessingEngineRefreshOptions, } from './types'; class Connection implements EntityProviderConnection { @@ -239,21 +238,6 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { this.stopFunc = undefined; } } - - async refresh(options: CatalogProcessingEngineRefreshOptions) { - await this.processingDatabase.transaction(async tx => { - const { entityRefs } = await this.processingDatabase.listAncestors(tx, { - entityRef: options.entityRef, - }); - const locationAncestor = entityRefs.find(ref => - ref.startsWith('location:'), - ); - - await this.processingDatabase.refresh(tx, { - entityRef: locationAncestor ?? options.entityRef, - }); - }); - } } // Helps wrap the timing and logging behaviors diff --git a/plugins/catalog-backend/src/next/DefaultRefreshService.test.ts b/plugins/catalog-backend/src/next/DefaultRefreshService.test.ts new file mode 100644 index 0000000000..5df57c6897 --- /dev/null +++ b/plugins/catalog-backend/src/next/DefaultRefreshService.test.ts @@ -0,0 +1,328 @@ +/* + * Copyright 2021 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 { getVoidLogger } from '@backstage/backend-common'; +import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; +import { createHash } from 'crypto'; +import { Knex } from 'knex'; +import { Logger } from 'winston'; +import { DatabaseManager } from './database/DatabaseManager'; +import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; +import { + DbRefreshStateReferencesRow, + DbRefreshStateRow, +} from './database/tables'; +import { ProcessingDatabase } from './database/types'; +import { DefaultCatalogProcessingEngine } from './DefaultCatalogProcessingEngine'; +import { EntityProcessingRequest } from './processing/types'; +import { Stitcher } from './stitching/Stitcher'; +import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; +import { v4 as uuid } from 'uuid'; +import { DefaultRefreshService } from './DefaultRefreshService'; + +describe('Refresh integration', () => { + const defaultLogger = getVoidLogger(); + const databases = TestDatabases.create({ + ids: ['POSTGRES_13', 'POSTGRES_9', 'SQLITE_3'], + }); + + async function createDatabase( + databaseId: TestDatabaseId, + logger: Logger = defaultLogger, + ) { + const knex = await databases.init(databaseId); + await DatabaseManager.createDatabase(knex); + return { + knex, + db: new DefaultProcessingDatabase({ + database: knex, + logger, + refreshInterval: () => 100, + }), + }; + } + + const createPopulatedEngine = async (options: { + db: ProcessingDatabase; + knex: Knex; + entities: Entity[]; + references: { [source: string]: string[] }; + entityProcessor?: (entity: Entity) => void; + }) => { + const { db, knex, entities, references, entityProcessor } = options; + + const entityMap = new Map( + entities.map(entity => [stringifyEntityRef(entity), entity]), + ); + + for (const entity of entities) { + await knex('refresh_state').insert({ + entity_id: uuid(), + entity_ref: stringifyEntityRef(entity), + unprocessed_entity: JSON.stringify(entity), + errors: '[]', + next_update_at: '2031-01-01 23:00:00', + last_discovery_at: '2021-04-01 13:37:00', + }); + } + + const entitiesWithParent = new Set(Object.values(references).flat()); + for (const entityRef of entityMap.keys()) { + if (!entitiesWithParent.has(entityRef)) { + await knex( + 'refresh_state_references', + ).insert({ + source_key: 'ConfigLocationProvider', + target_entity_ref: entityRef, + }); + } + } + for (const [sourceRef, targetRefs] of Object.entries(references)) { + for (const targetRef of targetRefs) { + await knex( + 'refresh_state_references', + ).insert({ + source_entity_ref: sourceRef, + target_entity_ref: targetRef, + }); + } + } + + const engine = new DefaultCatalogProcessingEngine( + defaultLogger, + [], + db, + { + async process(request: EntityProcessingRequest) { + const entityRef = stringifyEntityRef(request.entity); + const entity = entityMap.get(entityRef); + if (!entity) { + throw new Error(`Unexpected entity: ${entityRef}`); + } + const deferredEntities = + references[entityRef]?.map(ref => { + const e = entityMap.get(ref); + if (!e) { + throw new Error(`Target entity not found: ${ref}`); + } + return { entity: e, locationKey: ref }; + }) || []; + + entityProcessor?.(entity); + + return { + ok: true, + completedEntity: { + ...entity, + metadata: { + ...entity.metadata, + annotations: { + ...entity.metadata.annotations, + 'refresh-completed': 'true', + }, + }, + }, + relations: [], + errors: [], + deferredEntities, + state: new Map(), + }; + }, + }, + new Stitcher(knex, defaultLogger), + () => createHash('sha1'), + 50, + ); + + return engine; + }; + + const waitForRefresh = async (knex: Knex, entityRef: string) => { + for (;;) { + const [result] = await knex('refresh_state') + .where('entity_ref', entityRef) + .select(); + + const entity = result.processed_entity + ? (JSON.parse(result.processed_entity) as Entity) + : undefined; + if (entity?.metadata?.annotations?.['refresh-completed']) { + // Reset the annotation so that we can run another verification + delete entity.metadata.annotations['refresh-completed']; + await knex('refresh_state') + .update({ + processed_entity: JSON.stringify(entity), + }) + .where('entity_ref', entityRef); + return true; + } + await new Promise(resolve => setTimeout(resolve, 500)); + } + }; + + it.each(databases.eachSupportedId())( + 'should refresh the parent location, %p', + async databaseId => { + const { knex, db } = await createDatabase(databaseId); + const refreshService = new DefaultRefreshService({ database: db }); + const engine = await createPopulatedEngine({ + db, + knex, + entities: [ + { + kind: 'Location', + apiVersion: '1.0.0', + metadata: { + name: 'myloc', + }, + }, + { + kind: 'Component', + apiVersion: '1.0.0', + metadata: { + name: 'mycomp', + }, + }, + ], + references: { + 'location:default/myloc': ['component:default/mycomp'], + }, + }); + + await engine.start(); + + await refreshService.refresh({ + entityRef: 'component:default/mycomp', + }); + + await expect( + waitForRefresh(knex, 'location:default/myloc'), + ).resolves.toBe(true); + + await engine.stop(); + }, + ); + + it.each(databases.eachSupportedId())( + 'should refresh the location further up the tree, %p', + async databaseId => { + const { knex, db } = await createDatabase(databaseId); + const refreshService = new DefaultRefreshService({ database: db }); + const engine = await createPopulatedEngine({ + db, + knex, + entities: [ + { + kind: 'Location', + apiVersion: '1.0.0', + metadata: { + name: 'myloc', + }, + }, + { + kind: 'Component', + apiVersion: '1.0.0', + metadata: { + name: 'mycomp', + }, + }, + { + kind: 'Api', + apiVersion: '1.0.0', + metadata: { + name: 'myapi', + }, + }, + ], + references: { + 'location:default/myloc': ['component:default/mycomp'], + 'component:default/mycomp': ['api:default/myapi'], + }, + }); + + await engine.start(); + + await refreshService.refresh({ + entityRef: 'api:default/myapi', + }); + + await expect(waitForRefresh(knex, 'api:default/myapi')).resolves.toBe( + true, + ); + + await engine.stop(); + }, + ); + + it.each(databases.eachSupportedId())( + 'should refresh even when parent has no changes', + async databaseId => { + let secondRound = false; + const { knex, db } = await createDatabase(databaseId); + const refreshService = new DefaultRefreshService({ database: db }); + const engine = await createPopulatedEngine({ + db, + knex, + entities: [ + { + kind: 'Location', + apiVersion: '1.0.0', + metadata: { + name: 'myloc', + }, + }, + { + kind: 'Component', + apiVersion: '1.0.0', + metadata: { + name: 'mycomp', + }, + }, + ], + references: { + 'location:default/myloc': ['component:default/mycomp'], + }, + entityProcessor: entity => { + if (entity.metadata.name === 'mycomp' && secondRound) { + entity.apiVersion = '2.0.0'; + } + }, + }); + + await engine.start(); + + await refreshService.refresh({ + entityRef: 'component:default/mycomp', + }); + + await expect( + waitForRefresh(knex, 'component:default/mycomp'), + ).resolves.toBe(true); + + secondRound = true; + + await refreshService.refresh({ + entityRef: 'component:default/mycomp', + }); + + await expect( + waitForRefresh(knex, 'component:default/mycomp'), + ).resolves.toBe(true); + + await engine.stop(); + }, + ); +}); diff --git a/plugins/catalog-backend/src/next/DefaultRefreshService.ts b/plugins/catalog-backend/src/next/DefaultRefreshService.ts new file mode 100644 index 0000000000..bb713fd355 --- /dev/null +++ b/plugins/catalog-backend/src/next/DefaultRefreshService.ts @@ -0,0 +1,46 @@ +/* + * Copyright 2021 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 { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; +import { RefreshOptions, RefreshService } from './types'; + +export class DefaultRefreshService implements RefreshService { + private database: DefaultProcessingDatabase; + + constructor(options: { database: DefaultProcessingDatabase }) { + this.database = options.database; + } + + async refresh(options: RefreshOptions) { + await this.database.transaction(async tx => { + const { entityRefs } = await this.database.listAncestors(tx, { + entityRef: options.entityRef, + }); + const locationAncestor = entityRefs.find(ref => + ref.startsWith('location:'), + ); + + if (locationAncestor) { + await this.database.refresh(tx, { + entityRef: locationAncestor, + }); + } + await this.database.refresh(tx, { + entityRef: options.entityRef, + }); + }); + } +} diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts index 9186fc3efe..a34be2ca6a 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/next/NextCatalogBuilder.ts @@ -77,6 +77,7 @@ import { } from './refresh'; import { CatalogEnvironment } from '../service/CatalogBuilder'; import { createNextRouter } from './NextRouter'; +import { DefaultRefreshService } from './DefaultRefreshService'; /** * A builder that helps wire up all of the component parts of the catalog. @@ -335,12 +336,14 @@ export class NextCatalogBuilder { locationStore, orchestrator, ); - + const refreshService = new DefaultRefreshService({ + database: processingDatabase, + }); const router = await createNextRouter({ entitiesCatalog, locationAnalyzer, locationService, - processingEngine, + refreshService, logger, config, }); diff --git a/plugins/catalog-backend/src/next/NextRouter.ts b/plugins/catalog-backend/src/next/NextRouter.ts index 4c8a43b10b..b9da91b30a 100644 --- a/plugins/catalog-backend/src/next/NextRouter.ts +++ b/plugins/catalog-backend/src/next/NextRouter.ts @@ -34,17 +34,13 @@ import { parseEntityTransformParams, } from '../service/request'; import { disallowReadonlyMode, validateRequestBody } from '../service/util'; -import { - CatalogProcessingEngine, - LocationService, - CatalogProcessingEngineRefreshOptions, -} from './types'; +import { RefreshService, RefreshOptions, LocationService } from './types'; export interface NextRouterOptions { entitiesCatalog?: EntitiesCatalog; locationAnalyzer?: LocationAnalyzer; locationService: LocationService; - processingEngine?: CatalogProcessingEngine; + refreshService?: RefreshService; logger: Logger; config: Config; } @@ -56,7 +52,7 @@ export async function createNextRouter( entitiesCatalog, locationAnalyzer, locationService, - processingEngine, + refreshService, config, logger, } = options; @@ -70,10 +66,10 @@ export async function createNextRouter( logger.info('Catalog is running in readonly mode'); } - if (processingEngine) { + if (refreshService) { router.post('/refresh', async (req, res) => { - const refreshOptions: CatalogProcessingEngineRefreshOptions = req.body; - await processingEngine.refresh(refreshOptions); + const refreshOptions: RefreshOptions = req.body; + await refreshService.refresh(refreshOptions); res.status(200).send(); }); } diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index a7a04c5f0b..472c79e516 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -550,7 +550,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { ); } - const parentRef = rows[0].source_entity_ref; + const parentRef = rows.find(r => r.source_entity_ref)?.source_entity_ref; if (!parentRef) { // We've reached the top of the tree which is the entityProvider. // In this case we refresh the entity itself. diff --git a/plugins/catalog-backend/src/next/index.ts b/plugins/catalog-backend/src/next/index.ts index b6c973c65d..f05ba903eb 100644 --- a/plugins/catalog-backend/src/next/index.ts +++ b/plugins/catalog-backend/src/next/index.ts @@ -28,5 +28,5 @@ export type { CatalogProcessingEngine, LocationService, LocationStore, - CatalogProcessingEngineRefreshOptions, + RefreshOptions, } from './types'; diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/next/types.ts index 6c77dab90c..fa058c4138 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/next/types.ts @@ -37,11 +37,29 @@ export interface LocationStore { export interface CatalogProcessingEngine { start(): Promise; stop(): Promise; - refresh(options: CatalogProcessingEngineRefreshOptions): Promise; } -/** @public */ -export type CatalogProcessingEngineRefreshOptions = { entityRef: string }; +/** + * Options for requesting a refresh of entities in the catalog. + * + * @public + */ +export type RefreshOptions = { + /** The reference to a single entity that should be refreshed */ + entityRef: string; +}; + +/** + * A service that manages refreshes of entities in the catalog. + * + * @public + */ +export interface RefreshService { + /** + * Request a refresh of entities in the catalog. + */ + refresh(options: RefreshOptions): Promise; +} export type EntityProviderMutation = | { type: 'full'; entities: DeferredEntity[] } diff --git a/plugins/catalog-backend/src/service/router.ts b/plugins/catalog-backend/src/service/router.ts index 144dc459bb..f1bb18c825 100644 --- a/plugins/catalog-backend/src/service/router.ts +++ b/plugins/catalog-backend/src/service/router.ts @@ -28,11 +28,7 @@ import { Logger } from 'winston'; import yn from 'yn'; import { EntitiesCatalog, LocationsCatalog } from '../catalog'; import { HigherOrderOperation, LocationAnalyzer } from '../ingestion/types'; -import { - LocationService, - CatalogProcessingEngine, - CatalogProcessingEngineRefreshOptions, -} from '../next/types'; +import { RefreshService, LocationService, RefreshOptions } from '../next/types'; import { basicEntityFilter, parseEntityFilterParams, @@ -51,7 +47,7 @@ export interface RouterOptions { higherOrderOperation?: HigherOrderOperation; locationAnalyzer?: LocationAnalyzer; locationService?: LocationService; - processingEngine?: CatalogProcessingEngine; + refreshService?: RefreshService; logger: Logger; config: Config; } @@ -65,7 +61,7 @@ export async function createRouter( higherOrderOperation, locationAnalyzer, locationService, - processingEngine, + refreshService, config, logger, } = options; @@ -79,10 +75,10 @@ export async function createRouter( logger.info('Catalog is running in readonly mode'); } - if (processingEngine) { + if (refreshService) { router.post('/refresh', async (req, res) => { - const refreshOptions: CatalogProcessingEngineRefreshOptions = req.body; - await processingEngine.refresh(refreshOptions); + const refreshOptions: RefreshOptions = req.body; + await refreshService.refresh(refreshOptions); res.status(200).send(); }); }