From eacc8e2b55b78c9cb08f6e77227b08cf806299e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fredrik=20Adel=C3=B6w?= Date: Tue, 29 Nov 2022 14:32:08 +0100 Subject: [PATCH] entity provider delta remove with refs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Fredrik Adelöw --- .changeset/fifty-news-stare.md | 6 +++ .../DefaultProcessingDatabase.test.ts | 8 +--- .../src/database/DefaultProcessingDatabase.ts | 2 +- plugins/catalog-backend/src/database/types.ts | 2 +- .../src/processing/connectEntityProviders.ts | 16 +++++++- plugins/catalog-node/api-report.md | 10 ++++- plugins/catalog-node/src/api/provider.ts | 38 ++++++++++++++----- 7 files changed, 59 insertions(+), 23 deletions(-) create mode 100644 .changeset/fifty-news-stare.md diff --git a/.changeset/fifty-news-stare.md b/.changeset/fifty-news-stare.md new file mode 100644 index 0000000000..24ad2e20e7 --- /dev/null +++ b/.changeset/fifty-news-stare.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-catalog-backend': patch +'@backstage/plugin-catalog-node': minor +--- + +Make it possible for entity providers to supply only entity refs, instead of full entities, in `delta` mutation deletions. diff --git a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts index 46b327733d..f766589fe7 100644 --- a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts @@ -991,13 +991,7 @@ describe('Default Processing Database', () => { added: [], removed: [ { - entity: { - apiVersion: '1.0.0', - metadata: { - name: 'new-root', - }, - kind: 'Location', - } as Entity, + entityRef: 'location:default/new-root', locationKey: 'file:/tmp/foobar', }, ], diff --git a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts index 3dc5325178..4a30ecaec6 100644 --- a/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts @@ -737,7 +737,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { deferred: e, hash: generateStableHash(e.entity), })), - toRemove: options.removed.map(e => stringifyEntityRef(e.entity)), + toRemove: options.removed.map(e => e.entityRef), }; } diff --git a/plugins/catalog-backend/src/database/types.ts b/plugins/catalog-backend/src/database/types.ts index 2d30f8bd86..345aee6ebd 100644 --- a/plugins/catalog-backend/src/database/types.ts +++ b/plugins/catalog-backend/src/database/types.ts @@ -81,7 +81,7 @@ export type ReplaceUnprocessedEntitiesOptions = | { sourceKey: string; added: DeferredEntity[]; - removed: DeferredEntity[]; + removed: { entityRef: string; locationKey?: string }[]; type: 'delta'; }; diff --git a/plugins/catalog-backend/src/processing/connectEntityProviders.ts b/plugins/catalog-backend/src/processing/connectEntityProviders.ts index a4795532f0..3eb638ce7a 100644 --- a/plugins/catalog-backend/src/processing/connectEntityProviders.ts +++ b/plugins/catalog-backend/src/processing/connectEntityProviders.ts @@ -17,6 +17,7 @@ import { Entity, entityEnvelopeSchemaValidator, + stringifyEntityRef, } from '@backstage/catalog-model'; import { ProcessingDatabase } from '../database/types'; import { @@ -50,13 +51,24 @@ class Connection implements EntityProviderConnection { }); } else if (mutation.type === 'delta') { this.check(mutation.added.map(e => e.entity)); - this.check(mutation.removed.map(e => e.entity)); + this.check( + mutation.removed + .map(e => ('entity' in e ? e.entity : undefined)) + .filter((e): e is Entity => Boolean(e)), + ); await db.transaction(async tx => { await db.replaceUnprocessedEntities(tx, { sourceKey: this.config.id, type: 'delta', added: mutation.added, - removed: mutation.removed, + removed: mutation.removed.map(r => + 'entityRef' in r + ? r + : { + entityRef: stringifyEntityRef(r.entity), + locationKey: r.locationKey, + }, + ), }); }); } diff --git a/plugins/catalog-node/api-report.md b/plugins/catalog-node/api-report.md index 09a05ec7d9..9e9045db84 100644 --- a/plugins/catalog-node/api-report.md +++ b/plugins/catalog-node/api-report.md @@ -139,10 +139,16 @@ export type EntityProviderMutation = | { type: 'delta'; added: DeferredEntity[]; - removed: DeferredEntity[]; + removed: ( + | DeferredEntity + | { + entityRef: string; + locationKey?: string; + } + )[]; }; -// @public (undocumented) +// @public export type EntityProviderRefreshOptions = { keys: string[]; }; diff --git a/plugins/catalog-node/src/api/provider.ts b/plugins/catalog-node/src/api/provider.ts index fc9a172e0d..a576f32022 100644 --- a/plugins/catalog-node/src/api/provider.ts +++ b/plugins/catalog-node/src/api/provider.ts @@ -17,16 +17,26 @@ import { DeferredEntity } from '../processing'; /** - * @public * A 'full' mutation replaces all existing entities created by this entity provider with new ones. * A 'delta' mutation can both add and remove entities provided by this provider. Previously provided * entities from a 'full' mutation are not removed. + * + * @public */ export type EntityProviderMutation = - | { type: 'full'; entities: DeferredEntity[] } - | { type: 'delta'; added: DeferredEntity[]; removed: DeferredEntity[] }; + | { + type: 'full'; + entities: DeferredEntity[]; + } + | { + type: 'delta'; + added: DeferredEntity[]; + removed: (DeferredEntity | { entityRef: string; locationKey?: string })[]; + }; /** + * The options given to an entity refresh operation. + * * @public */ export type EntityProviderRefreshOptions = { @@ -34,30 +44,38 @@ export type EntityProviderRefreshOptions = { }; /** - * The EntityProviderConnection is the connection between the catalog and the entity provider. - * The EntityProvider use this connection to add and remove entities from the catalog. + * The connection between the catalog and the entity provider. + * Entity providers use this connection to add and remove entities from the catalog. + * * @public */ export interface EntityProviderConnection { /** - * Applies either a full or delta update to the catalog engine. + * Applies either a full or a delta update to the catalog engine. */ applyMutation(mutation: EntityProviderMutation): Promise; /** - * Schedules a refresh on all of the entities that has a matching refresh key associated with the provided keys. + * Schedules a refresh on all of the entities that have a matching refresh key associated with the provided keys. */ refresh(options: EntityProviderRefreshOptions): Promise; } /** - * An EntityProvider is able to provide entities to the catalog. + * An entity provider is able to provide entities to the catalog. * See https://backstage.io/docs/features/software-catalog/life-of-an-entity for more details. + * * @public */ export interface EntityProvider { - /** Unique provider name used internally for caching. */ + /** + * The name of the provider, which must be unique for all providers that are + * active in a catalog, and stable over time since emitted entities are + * related to the provider by this name. + */ getProviderName(): string; - /** Connect is called upon initialization by the catalog engine. */ + /** + * Called upon initialization by the catalog engine. + */ connect(connection: EntityProviderConnection): Promise; }