From 76ebabc730ab1371922c89f3b3e3724cfe380cab Mon Sep 17 00:00:00 2001 From: Johan Haals Date: Mon, 13 Sep 2021 15:21:51 +0200 Subject: [PATCH] Add listAncestors method, simplify refresh Co-authored-by: Patrik Oldsberg Signed-off-by: Johan Haals --- .../next/DefaultCatalogProcessingEngine.ts | 11 +++++- .../database/DefaultProcessingDatabase.ts | 34 +++++++++++-------- .../src/next/database/types.ts | 18 ++++++++++ 3 files changed, 47 insertions(+), 16 deletions(-) diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts index 6e3f6589d2..998acb230a 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts @@ -242,7 +242,16 @@ export class DefaultCatalogProcessingEngine implements CatalogProcessingEngine { async refresh(options: EntityRefreshOptions) { await this.processingDatabase.transaction(async tx => { - await this.processingDatabase.refresh(tx, options); + 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, + }); }); } } diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index 3ca8fdb10d..a7a04c5f0b 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -39,6 +39,8 @@ import { RefreshOptions, ReplaceUnprocessedEntitiesOptions, UpdateProcessedEntityOptions, + ListAncestorsOptions, + ListAncestorsResult, } from './types'; // The number of items that are sent per batch to the database layer, when @@ -46,7 +48,7 @@ import { // errors in the underlying engine due to exceeding query limits, but large // enough to get the speed benefits. const BATCH_SIZE = 50; -const MAX_REFRESH_DEPTH = 10; +const MAX_ANCESTOR_DEPTH = 32; export class DefaultProcessingDatabase implements ProcessingDatabase { constructor( @@ -516,18 +518,20 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { }; } - async refresh(txOpaque: Transaction, options: RefreshOptions): Promise { + async listAncestors( + txOpaque: Transaction, + options: ListAncestorsOptions, + ): Promise { const tx = txOpaque as Knex.Transaction; const { entityRef } = options; - - let refreshTarget = entityRef; + const entityRefs = new Array(); let currentRef = entityRef; let depth = 0; for (;;) { - if (depth++ > MAX_REFRESH_DEPTH) { + if (depth++ > MAX_ANCESTOR_DEPTH) { throw new Error( - `Unable to refresh Entity ${entityRef}, maximum refresh depth of ${MAX_REFRESH_DEPTH} reached`, + `Unable receive ancestors for ${entityRef}, reached maximum depth of ${MAX_ANCESTOR_DEPTH}`, ); } @@ -550,22 +554,22 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { if (!parentRef) { // We've reached the top of the tree which is the entityProvider. // In this case we refresh the entity itself. - break; - } - if (parentRef.startsWith('location:')) { - refreshTarget = parentRef; - break; + return { entityRefs }; } + entityRefs.push(parentRef); currentRef = parentRef; } + } + + async refresh(txOpaque: Transaction, options: RefreshOptions): Promise { + const tx = txOpaque as Knex.Transaction; + const { entityRef } = options; const updateResult = await tx('refresh_state') - .where({ entity_ref: refreshTarget }) + .where({ entity_ref: entityRef }) .update({ next_update_at: tx.fn.now() }); if (updateResult === 0) { - throw new ConflictError( - `Failed to schedule ${refreshTarget} for refresh`, - ); + throw new ConflictError(`Failed to schedule ${entityRef} for refresh`); } } diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/next/database/types.ts index f3e70ea260..3dfe8e5592 100644 --- a/plugins/catalog-backend/src/next/database/types.ts +++ b/plugins/catalog-backend/src/next/database/types.ts @@ -83,6 +83,14 @@ export type RefreshOptions = { entityRef: string; }; +export type ListAncestorsOptions = { + entityRef: string; +}; + +export type ListAncestorsResult = { + entityRefs: string[]; +}; + export interface ProcessingDatabase { transaction(fn: (tx: Transaction) => Promise): Promise; @@ -122,4 +130,14 @@ export interface ProcessingDatabase { * Schedules a refresh of a given entityRef. */ refresh(txOpaque: Transaction, options: RefreshOptions): Promise; + + /** + * Lists all ancestors of a given entityRef. + * + * The returned list is ordered from the most immediate ancestor to the most distant one. + */ + listAncestors( + txOpaque: Transaction, + options: ListAncestorsOptions, + ): Promise; }