From 9eabf3003a89eab2dac5f86547157106a2638ac5 Mon Sep 17 00:00:00 2001 From: hided62 Date: Sat, 15 Aug 2026 16:37:01 +0000 Subject: [PATCH] =?UTF-8?q?fix(engine):=20=EB=8C=80=EA=B7=9C=EB=AA=A8=20?= =?UTF-8?q?=ED=84=B4=20=EC=A0=80=EC=9E=A5=20=EC=99=84=EB=A3=8C=20=EC=8B=9C?= =?UTF-8?q?=EA=B0=84=20=ED=99=95=EB=B3=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/game-engine/src/turn/databaseHooks.ts | 36 +++++++++++------------ 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/app/game-engine/src/turn/databaseHooks.ts b/app/game-engine/src/turn/databaseHooks.ts index e982be26..2a2c2505 100644 --- a/app/game-engine/src/turn/databaseHooks.ts +++ b/app/game-engine/src/turn/databaseHooks.ts @@ -897,6 +897,10 @@ export const createDatabaseTurnHooks = async ( const connector = createGamePostgresConnector({ url: databaseUrl }); await connector.connect(); const prisma = connector.prisma; + // Prisma's 5-second default matches the normal turn execution budget too + // closely. A populated season can finish the turn but expire while flushing + // it, which rolls the transaction back and marks the profile PAUSED. + const transactionOptions = { timeout: options?.transactionTimeoutMs ?? 30_000 }; let committedReadModelChanges: RealtimeReadModelChanges | null = null; const readModelBaseline = createRealtimeReadModelBaseline(world); @@ -1391,10 +1395,7 @@ export const createDatabaseTurnHooks = async ( if (transaction) { await persist(transaction); } else { - await prisma.$transaction( - persist, - options?.transactionTimeoutMs ? { timeout: options.transactionTimeoutMs } : undefined - ); + await prisma.$transaction(persist, transactionOptions); } const readModelChanges = mergePersistedVisibleLogChanges( @@ -1425,21 +1426,18 @@ export const createDatabaseTurnHooks = async ( committedReadModelChanges = committed.readModelChanges; }, executeCommand: async (requestId, execute) => { - const committed = await prisma.$transaction( - async (transaction) => { - const directLogFloor = - ( - await transaction.logEntry.findFirst({ - orderBy: { id: 'desc' }, - select: { id: true }, - }) - )?.id ?? 0; - const result = await execute({ db: transaction }); - const persisted = await persistChanges(transaction, { requestId, result }, directLogFloor); - return { result, persisted }; - }, - options?.transactionTimeoutMs ? { timeout: options.transactionTimeoutMs } : undefined - ); + const committed = await prisma.$transaction(async (transaction) => { + const directLogFloor = + ( + await transaction.logEntry.findFirst({ + orderBy: { id: 'desc' }, + select: { id: true }, + }) + )?.id ?? 0; + const result = await execute({ db: transaction }); + const persisted = await persistChanges(transaction, { requestId, result }, directLogFloor); + return { result, persisted }; + }, transactionOptions); committed.persisted.acknowledge(); committedReadModelChanges = committed.persisted.readModelChanges; return committed.result;