feat: deduplicate locations on insert

This commit is contained in:
Ivan Shmidt
2020-05-15 14:25:07 +02:00
parent 16df7e9ce0
commit 6bee3ce985
3 changed files with 37 additions and 4 deletions
+1
View File
@@ -21,6 +21,7 @@
"helmet": "^3.22.0",
"knex": "^0.21.1",
"morgan": "^1.10.0",
"sqlite3": "^4.2.0",
"uuid": "^8.0.0",
"winston": "^3.2.1",
"yaml": "^1.9.2",
@@ -60,4 +60,20 @@ describe('DatabaseCatalog', () => {
/Found no location/,
);
});
it('instead of adding second location with the same target, returns existing one', async () => {
// Prepare
const catalog = new DatabaseCatalog(database, logger);
const input = { type: 'a', target: 'b' };
const output1 = await catalog.addLocation(input);
// Try to insert the same location
const output2 = await catalog.addLocation(input);
const locations = await catalog.locations();
// Output is the same
expect(output2).toEqual(output1);
// Locations contain only one record
expect(locations).toEqual([output1]);
});
});
@@ -53,7 +53,7 @@ export class DatabaseCatalog implements Catalog {
name: descriptor.metadata.name,
};
await this.database.transaction(async (tx) => {
await this.database.transaction(async tx => {
// TODO(freben): Currently, several locations can compete for the same component
const count = await tx('components')
.where({ name: component.name })
@@ -74,7 +74,9 @@ export class DatabaseCatalog implements Catalog {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async component(name: string): Promise<Component> {
const items = await this.database('components').where({ name }).select();
const items = await this.database('components')
.where({ name })
.select();
if (!items.length) {
throw new NotFoundError(`Found no component with name ${name}`);
}
@@ -82,6 +84,10 @@ export class DatabaseCatalog implements Catalog {
}
async addLocation(location: AddLocationRequest): Promise<Location> {
const existingLocation = await this.locationByTarget(location.target);
if (existingLocation) {
return existingLocation;
}
const id = uuidv4();
const { type, target } = location;
await this.database('locations').insert({ id, type, target });
@@ -89,7 +95,9 @@ export class DatabaseCatalog implements Catalog {
}
async removeLocation(id: string): Promise<void> {
const result = await this.database('locations').where({ id }).del();
const result = await this.database('locations')
.where({ id })
.del();
if (!result) {
throw new NotFoundError(`Found no location with ID ${id}`);
@@ -97,13 +105,21 @@ export class DatabaseCatalog implements Catalog {
}
async location(id: string): Promise<Location> {
const items = await this.database('locations').where({ id }).select();
const items = await this.database('locations')
.where({ id })
.select();
if (!items.length) {
throw new NotFoundError(`Found no location with ID ${id}`);
}
return items[0];
}
private async locationByTarget(
target: string,
): Promise<Location | undefined> {
return (await this.locations()).find(l => l.target === target);
}
async locations(): Promise<Location[]> {
return await this.database('locations').select();
}