Merge pull request #17252 from schultzp2020/refactor-default-entities-catalog

Refactor DefaultEntitiesCatalog.ts
This commit is contained in:
Johan Haals
2023-05-08 16:53:49 +02:00
committed by GitHub
2 changed files with 46 additions and 40 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-catalog-backend': patch
---
Internal refactoring for performance in the service handlers
@@ -64,43 +64,47 @@ const defaultSortField: EntityOrder = {
const DEFAULT_LIMIT = 20;
function parsePagination(input?: EntityPagination): {
limit?: number;
offset?: number;
} {
function parsePagination(input?: EntityPagination): EntityPagination {
if (!input) {
return {};
}
let { limit, offset } = input;
if (input.after !== undefined) {
let cursor;
try {
const json = Buffer.from(input.after, 'base64').toString('utf8');
cursor = JSON.parse(json);
} catch {
throw new InputError('Malformed after cursor, could not be parsed');
if (input.after === undefined) {
return { limit, offset };
}
let cursor;
try {
const json = Buffer.from(input.after, 'base64').toString('utf8');
cursor = JSON.parse(json);
} catch {
throw new InputError('Malformed after cursor, could not be parsed');
}
if (cursor.limit !== undefined) {
if (!Number.isInteger(cursor.limit)) {
throw new InputError('Malformed after cursor, limit was not an number');
}
if (cursor.limit !== undefined) {
if (!Number.isInteger(cursor.limit)) {
throw new InputError('Malformed after cursor, limit was not an number');
}
limit = cursor.limit;
}
if (cursor.offset !== undefined) {
if (!Number.isInteger(cursor.offset)) {
throw new InputError('Malformed after cursor, offset was not a number');
}
offset = cursor.offset;
limit = cursor.limit;
}
if (cursor.offset !== undefined) {
if (!Number.isInteger(cursor.offset)) {
throw new InputError('Malformed after cursor, offset was not a number');
}
offset = cursor.offset;
}
return { limit, offset };
}
function stringifyPagination(input: { limit: number; offset: number }) {
const json = JSON.stringify({ limit: input.limit, offset: input.offset });
function stringifyPagination(
input: Required<Omit<EntityPagination, 'after'>>,
): string {
const { limit, offset } = input;
const json = JSON.stringify({ limit, offset });
const base64 = Buffer.from(json, 'utf8').toString('base64');
return base64;
}
@@ -111,24 +115,21 @@ function addCondition(
filter: EntitiesSearchFilter,
negate: boolean = false,
entityIdField = 'entity_id',
) {
): void {
const key = filter.key.toLowerCase();
const values = filter.values?.map(v => v.toLowerCase());
// NOTE(freben): This used to be a set of OUTER JOIN, which may seem to
// make a lot of sense. However, it had abysmal performance on sqlite
// when datasets grew large, so we're using IN instead.
const matchQuery = db<DbSearchRow>('search')
.select('search.entity_id')
.where({ key: filter.key.toLowerCase() })
.where({ key })
.andWhere(function keyFilter() {
if (filter.values) {
if (filter.values.length === 1) {
this.where({ value: filter.values[0].toLowerCase() });
} else {
this.andWhere(
'value',
'in',
filter.values.map(v => v.toLowerCase()),
);
}
if (values?.length === 1) {
this.where({ value: values.at(0) });
} else if (values) {
this.andWhere('value', 'in', values);
}
});
queryBuilder.andWhere(entityIdField, negate ? 'not in' : 'in', matchQuery);
@@ -159,16 +160,16 @@ function parseFilter(
negate: boolean = false,
entityIdField = 'entity_id',
): Knex.QueryBuilder {
if (isNegationEntityFilter(filter)) {
return parseFilter(filter.not, query, db, !negate, entityIdField);
}
if (isEntitiesSearchFilter(filter)) {
return query.andWhere(function filterFunction() {
addCondition(this, db, filter, negate, entityIdField);
});
}
if (isNegationEntityFilter(filter)) {
return parseFilter(filter.not, query, db, !negate, entityIdField);
}
return query[negate ? 'andWhereNot' : 'andWhere'](function filterFunction() {
if (isOrEntityFilter(filter)) {
for (const subFilter of filter.anyOf ?? []) {