From 698e823bbe171ac68b9b27c2d79ea9a03ee49d16 Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Tue, 29 Jun 2021 16:58:09 +0200 Subject: [PATCH] catalog-backend: fix unprocessed entity conflict handling when using postgres Co-authored-by: blam Co-authored-by: Johan Haals Signed-off-by: Patrik Oldsberg --- .../database/DefaultProcessingDatabase.ts | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts index 67b83bdb34..d18f194a57 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts @@ -354,7 +354,7 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { if (refreshResult === 0) { // In the event that we can't update an existing refresh state, we first try to insert a new row try { - await tx('refresh_state').insert({ + let query = tx('refresh_state').insert({ entity_id: uuid(), entity_ref: entityRef, unprocessed_entity: serializedEntity, @@ -363,7 +363,28 @@ export class DefaultProcessingDatabase implements ProcessingDatabase { next_update_at: tx.fn.now(), last_discovery_at: tx.fn.now(), }); + + // TODO(Rugvip): only tested towards Postgres and SQLite + // We have to do this because the only way to detect if there was a conflict with + // SQLite is to catch the error, while Postgres needs to ignore the conflict to not + // break the ongoing transaction. + if (tx.client.config.client !== 'sqlite3') { + query = query.onConflict('entity_ref').ignore(); + } + + const result = await query; + if (result.rowCount === 0) { + throw new ConflictError( + 'Insert failed due to conflicting entity_ref', + ); + } } catch (error) { + if ( + !error.message.contains('UNIQUE constraint failed') && + error.name !== 'ConflictError' + ) { + throw error; + } // If the row can't be inserted, we have a conflict, but it could be either // because of a conflicting locationKey or a race with another instance, so check // whether the conflicting entity has the same entityRef but a different locationKey