From 2af32ac4b03a4c709ba27629ca2272f7d09a783c Mon Sep 17 00:00:00 2001 From: Stephan Kulla Date: Tue, 28 May 2024 10:47:53 +0200 Subject: [PATCH] wip: Replay transactions on deadlock --- packages/server/src/database.ts | 32 ++++++++++++++++++++++ packages/server/src/schema/events/event.ts | 10 ++----- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/packages/server/src/database.ts b/packages/server/src/database.ts index 9b6607858..3d20d6306 100644 --- a/packages/server/src/database.ts +++ b/packages/server/src/database.ts @@ -16,6 +16,38 @@ export class Database { this.state = { type: 'OutsideOfTransaction' } } + public async withTransaction(fn: () => Promise) { + const transaction = await this.beginTransaction() + + try { + await fn() + + await transaction.commit() + } catch (error: unknown) { + console.log(error) + + if (this.state.type !== 'OutsideOfTransaction') { + console.log( + await this.state.transaction.query('SHOW ENGINE INNODB STATUS;'), + ) + } + + await transaction.rollback() + + if ( + error instanceof Error && + 'code' in error && + error.code === 'ER_LOCK_DEADLOCK' + ) { + console.log('deadlock detected, retrying') + + await this.withTransaction(fn) + } else { + throw error + } + } + } + public async beginTransaction() { if (this.state.type === 'OutsideOfTransaction') { const transaction = await this.pool.getConnection() diff --git a/packages/server/src/schema/events/event.ts b/packages/server/src/schema/events/event.ts index b98a62a6b..3da2968a6 100644 --- a/packages/server/src/schema/events/event.ts +++ b/packages/server/src/schema/events/event.ts @@ -34,9 +34,7 @@ export async function createEvent( const abstractEventPayload = toDatabaseRepresentation(payload) const { type, actorId, objectId, instance } = abstractEventPayload - const transaction = await database.beginTransaction() - - try { + await database.withTransaction(async () => { const { insertId: eventId } = await database.mutate( ` INSERT INTO event_log (actor_id, event_id, uuid_id, instance_id) @@ -83,11 +81,7 @@ export async function createEvent( const event = { ...abstractEventPayload, id: eventId } await createNotifications(event, { database }) - - await transaction.commit() - } finally { - await transaction.rollback() - } + }) } async function createNotifications(