catalog-backend: review fixes
This commit is contained in:
@@ -32,8 +32,8 @@ export const RELATION_OWNER_OF = 'ownerOf';
|
||||
/**
|
||||
* A relation with an API entity, typically from a component or system
|
||||
*/
|
||||
export const RELATION_IMPLEMENTED_BY = 'implementedBy';
|
||||
export const RELATION_IMPLEMENTS = 'implements';
|
||||
export const RELATION_CONSUMES_API = 'consumesApi';
|
||||
export const RELATION_PROVIDES_API = 'providesApi';
|
||||
|
||||
/**
|
||||
* A relation denoting a dependency on another entity.
|
||||
|
||||
@@ -18,7 +18,7 @@ import { getVoidLogger } from '@backstage/backend-common';
|
||||
import type { Entity } from '@backstage/catalog-model';
|
||||
import { Database, DatabaseManager } from '../database';
|
||||
import { DatabaseEntitiesCatalog } from './DatabaseEntitiesCatalog';
|
||||
import { EntityMutationRequest } from './types';
|
||||
import { EntityUpsertRequest } from './types';
|
||||
|
||||
describe('DatabaseEntitiesCatalog', () => {
|
||||
let db: jest.Mocked<Database>;
|
||||
@@ -272,8 +272,8 @@ describe('DatabaseEntitiesCatalog', () => {
|
||||
await DatabaseManager.createTestDatabase(),
|
||||
getVoidLogger(),
|
||||
);
|
||||
const entities: EntityMutationRequest[] = [];
|
||||
for (let i = 0; i < 200; ++i) {
|
||||
const entities: EntityUpsertRequest[] = [];
|
||||
for (let i = 0; i < 300; ++i) {
|
||||
entities.push({
|
||||
entity: {
|
||||
apiVersion: 'a',
|
||||
@@ -286,21 +286,21 @@ describe('DatabaseEntitiesCatalog', () => {
|
||||
|
||||
await catalog.batchAddOrUpdateEntities(entities);
|
||||
const afterFirst = await catalog.entities();
|
||||
expect(afterFirst.length).toBe(200);
|
||||
expect(afterFirst.length).toBe(300);
|
||||
|
||||
entities[40].entity.metadata.op = 'changed';
|
||||
entities.push({
|
||||
entity: {
|
||||
apiVersion: 'a',
|
||||
kind: 'k',
|
||||
metadata: { name: `n200`, op: 'added' },
|
||||
metadata: { name: `n300`, op: 'added' },
|
||||
},
|
||||
relations: [],
|
||||
});
|
||||
|
||||
await catalog.batchAddOrUpdateEntities(entities);
|
||||
const afterSecond = await catalog.entities();
|
||||
expect(afterSecond.length).toBe(201);
|
||||
expect(afterSecond.length).toBe(301);
|
||||
expect(afterSecond.find(e => e.metadata.op === 'changed')).toBeDefined();
|
||||
expect(afterSecond.find(e => e.metadata.op === 'added')).toBeDefined();
|
||||
}, 10000);
|
||||
|
||||
@@ -31,8 +31,8 @@ import type { Database, DbEntityResponse, EntityFilters } from '../database';
|
||||
import { durationText } from '../util/timing';
|
||||
import type {
|
||||
EntitiesCatalog,
|
||||
EntityMutationRequest,
|
||||
EntityMutationResponse,
|
||||
EntityUpsertRequest,
|
||||
EntityUpsertResponse,
|
||||
} from './types';
|
||||
|
||||
type BatchContext = {
|
||||
@@ -134,9 +134,9 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog {
|
||||
* @param locationId The location that they all belong to
|
||||
*/
|
||||
async batchAddOrUpdateEntities(
|
||||
requests: EntityMutationRequest[],
|
||||
requests: EntityUpsertRequest[],
|
||||
locationId?: string,
|
||||
): Promise<EntityMutationResponse[]> {
|
||||
): Promise<EntityUpsertResponse[]> {
|
||||
// Group the entities by unique kind+namespace combinations
|
||||
const entitiesByKindAndNamespace = groupBy(requests, ({ entity }) => {
|
||||
const name = getEntityName(entity);
|
||||
@@ -144,7 +144,7 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog {
|
||||
});
|
||||
|
||||
const limiter = limiterFactory(BATCH_CONCURRENCY);
|
||||
const tasks: Promise<EntityMutationResponse[]>[] = [];
|
||||
const tasks: Promise<EntityUpsertResponse[]>[] = [];
|
||||
|
||||
for (const groupRequests of Object.values(entitiesByKindAndNamespace)) {
|
||||
const { kind, namespace } = getEntityName(groupRequests[0].entity);
|
||||
@@ -157,7 +157,7 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog {
|
||||
limiter(async () => {
|
||||
const first = serializeEntityRef(batch[0].entity);
|
||||
const last = serializeEntityRef(batch[batch.length - 1].entity);
|
||||
const modifiedEntityIds: EntityMutationResponse[] = [];
|
||||
const modifiedEntityIds: EntityUpsertResponse[] = [];
|
||||
this.logger.debug(
|
||||
`Considering batch ${first}-${last} (${batch.length} entries)`,
|
||||
);
|
||||
@@ -224,12 +224,12 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog {
|
||||
// produce the list of entities to be added, and the list of entities to be
|
||||
// updated
|
||||
private async analyzeBatch(
|
||||
requests: EntityMutationRequest[],
|
||||
requests: EntityUpsertRequest[],
|
||||
{ kind, namespace }: BatchContext,
|
||||
): Promise<{
|
||||
toAdd: EntityMutationRequest[];
|
||||
toUpdate: EntityMutationRequest[];
|
||||
toIgnore: EntityMutationRequest[];
|
||||
toAdd: EntityUpsertRequest[];
|
||||
toUpdate: EntityUpsertRequest[];
|
||||
toIgnore: EntityUpsertRequest[];
|
||||
}> {
|
||||
const markTimestamp = process.hrtime();
|
||||
|
||||
@@ -244,9 +244,9 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog {
|
||||
oldEntities.map(e => [e.metadata.name, e]),
|
||||
);
|
||||
|
||||
const toAdd: EntityMutationRequest[] = [];
|
||||
const toUpdate: EntityMutationRequest[] = [];
|
||||
const toIgnore: EntityMutationRequest[] = [];
|
||||
const toAdd: EntityUpsertRequest[] = [];
|
||||
const toUpdate: EntityUpsertRequest[] = [];
|
||||
const toIgnore: EntityUpsertRequest[] = [];
|
||||
|
||||
for (const request of requests) {
|
||||
const newEntity = request.entity;
|
||||
@@ -275,9 +275,9 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog {
|
||||
// Efficiently adds the given entities to storage, under the assumption that
|
||||
// they do not conflict with any existing entities
|
||||
private async batchAdd(
|
||||
requests: EntityMutationRequest[],
|
||||
requests: EntityUpsertRequest[],
|
||||
{ locationId }: BatchContext,
|
||||
): Promise<EntityMutationResponse[]> {
|
||||
): Promise<EntityUpsertResponse[]> {
|
||||
const markTimestamp = process.hrtime();
|
||||
|
||||
const res = await this.database.transaction(
|
||||
@@ -306,11 +306,11 @@ export class DatabaseEntitiesCatalog implements EntitiesCatalog {
|
||||
// Efficiently updates the given entities into storage, under the assumption
|
||||
// that there already exist entities with the same names
|
||||
private async batchUpdate(
|
||||
requests: EntityMutationRequest[],
|
||||
requests: EntityUpsertRequest[],
|
||||
{ locationId }: BatchContext,
|
||||
): Promise<EntityMutationResponse[]> {
|
||||
): Promise<EntityUpsertResponse[]> {
|
||||
const markTimestamp = process.hrtime();
|
||||
const responseIds: EntityMutationResponse[] = [];
|
||||
const responseIds: EntityUpsertResponse[] = [];
|
||||
// TODO(freben): Still not batched
|
||||
for (const entity of requests) {
|
||||
const res = await this.addOrUpdateEntity(entity.entity, locationId);
|
||||
|
||||
@@ -21,12 +21,12 @@ import type { EntityFilters } from '../database';
|
||||
// Entities
|
||||
//
|
||||
|
||||
export type EntityMutationRequest = {
|
||||
export type EntityUpsertRequest = {
|
||||
entity: Entity;
|
||||
relations: EntityRelationSpec[];
|
||||
};
|
||||
|
||||
export type EntityMutationResponse = {
|
||||
export type EntityUpsertResponse = {
|
||||
entityId: string;
|
||||
};
|
||||
|
||||
@@ -41,9 +41,9 @@ export type EntitiesCatalog = {
|
||||
* @param locationId The location that they all belong to
|
||||
*/
|
||||
batchAddOrUpdateEntities(
|
||||
entities: EntityMutationRequest[],
|
||||
entities: EntityUpsertRequest[],
|
||||
locationId?: string,
|
||||
): Promise<EntityMutationResponse[]>;
|
||||
): Promise<EntityUpsertResponse[]>;
|
||||
};
|
||||
|
||||
//
|
||||
|
||||
@@ -103,10 +103,6 @@ export class HigherOrderOperations implements HigherOrderOperation {
|
||||
location.id,
|
||||
);
|
||||
|
||||
if (writtenEntities.length === 0) {
|
||||
return { location, entities: [] };
|
||||
}
|
||||
|
||||
const entities = await this.entitiesCatalog.entities({
|
||||
'metadata.uid': writtenEntities.map(e => e.entityId),
|
||||
});
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
ComponentEntityV1alpha1,
|
||||
RELATION_OWNED_BY,
|
||||
RELATION_OWNER_OF,
|
||||
getEntityName,
|
||||
} from '@backstage/catalog-model';
|
||||
import { CatalogProcessor, CatalogProcessorEmit } from './types';
|
||||
import * as result from './results';
|
||||
@@ -46,11 +47,7 @@ export class OwnerRelationProcessor implements CatalogProcessor {
|
||||
if (owner) {
|
||||
const namespace = entity.metadata.namespace ?? ENTITY_DEFAULT_NAMESPACE;
|
||||
|
||||
const selfRef = {
|
||||
kind: entity.kind,
|
||||
name: entity.metadata.name,
|
||||
namespace,
|
||||
};
|
||||
const selfRef = getEntityName(entity);
|
||||
const ownerRef = parseEntityRef(owner, {
|
||||
defaultKind: 'group',
|
||||
defaultNamespace: namespace,
|
||||
@@ -58,15 +55,15 @@ export class OwnerRelationProcessor implements CatalogProcessor {
|
||||
|
||||
emit(
|
||||
result.relation({
|
||||
type: RELATION_OWNED_BY,
|
||||
source: selfRef,
|
||||
type: RELATION_OWNED_BY,
|
||||
target: ownerRef,
|
||||
}),
|
||||
);
|
||||
emit(
|
||||
result.relation({
|
||||
type: RELATION_OWNER_OF,
|
||||
source: ownerRef,
|
||||
type: RELATION_OWNER_OF,
|
||||
target: selfRef,
|
||||
}),
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user