From 132e848fdc7bf2457f44f19f50c33933e3209d7a Mon Sep 17 00:00:00 2001 From: Mononaut Date: Sat, 3 Dec 2022 10:49:10 +0900 Subject: [PATCH] Fix block summaries repo upsert race condition --- backend/src/api/websocket-handler.ts | 2 +- .../repositories/BlocksSummariesRepository.ts | 41 +++++++++++++------ 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/backend/src/api/websocket-handler.ts b/backend/src/api/websocket-handler.ts index 31224fc0c..246b5b90d 100644 --- a/backend/src/api/websocket-handler.ts +++ b/backend/src/api/websocket-handler.ts @@ -439,7 +439,7 @@ class WebsocketHandler { }; }) : []; - BlocksSummariesRepository.$saveSummary({ + BlocksSummariesRepository.$saveTemplate({ height: block.height, template: { id: block.id, diff --git a/backend/src/repositories/BlocksSummariesRepository.ts b/backend/src/repositories/BlocksSummariesRepository.ts index 28b3cc7eb..1406a1d07 100644 --- a/backend/src/repositories/BlocksSummariesRepository.ts +++ b/backend/src/repositories/BlocksSummariesRepository.ts @@ -17,19 +17,16 @@ class BlocksSummariesRepository { return undefined; } - public async $saveSummary(params: { height: number, mined?: BlockSummary, template?: BlockSummary}) { - const blockId = params.mined?.id ?? params.template?.id; + public async $saveSummary(params: { height: number, mined?: BlockSummary}) { + const blockId = params.mined?.id; try { - const [dbSummary]: any[] = await DB.query(`SELECT * FROM blocks_summaries WHERE id = "${blockId}"`); - if (dbSummary.length === 0) { // First insertion - await DB.query(`INSERT INTO blocks_summaries VALUE (?, ?, ?, ?)`, [ - params.height, blockId, JSON.stringify(params.mined?.transactions ?? []), JSON.stringify(params.template?.transactions ?? []) - ]); - } else if (params.mined !== undefined) { // Update mined block summary - await DB.query(`UPDATE blocks_summaries SET transactions = ? WHERE id = "${params.mined.id}"`, [JSON.stringify(params.mined.transactions)]); - } else if (params.template !== undefined) { // Update template block summary - await DB.query(`UPDATE blocks_summaries SET template = ? WHERE id = "${params.template.id}"`, [JSON.stringify(params.template?.transactions)]); - } + const transactions = JSON.stringify(params.mined?.transactions || []); + await DB.query(` + INSERT INTO blocks_summaries (height, id, transactions, template) + VALUE (?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + transactions = ? + `, [params.height, blockId, transactions, '[]', transactions]); } catch (e: any) { if (e.errno === 1062) { // ER_DUP_ENTRY - This scenario is possible upon node backend restart logger.debug(`Cannot save block summary for ${blockId} because it has already been indexed, ignoring`); @@ -40,6 +37,26 @@ class BlocksSummariesRepository { } } + public async $saveTemplate(params: { height: number, template: BlockSummary}) { + const blockId = params.template?.id; + try { + const transactions = JSON.stringify(params.template?.transactions || []); + await DB.query(` + INSERT INTO blocks_summaries (height, id, transactions, template) + VALUE (?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + template = ? + `, [params.height, blockId, '[]', transactions, transactions]); + } catch (e: any) { + if (e.errno === 1062) { // ER_DUP_ENTRY - This scenario is possible upon node backend restart + logger.debug(`Cannot save block template for ${blockId} because it has already been indexed, ignoring`); + } else { + logger.debug(`Cannot save block template for ${blockId}. Reason: ${e instanceof Error ? e.message : e}`); + throw e; + } + } + } + public async $getIndexedSummariesId(): Promise { try { const [rows]: any[] = await DB.query(`SELECT id from blocks_summaries`);