fix(engine): 대규모 턴 저장 완료 시간 확보

This commit is contained in:
2026-08-15 16:37:01 +00:00
parent 50a31d14bf
commit 9eabf3003a
+17 -19
View File
@@ -897,6 +897,10 @@ export const createDatabaseTurnHooks = async (
const connector = createGamePostgresConnector({ url: databaseUrl }); const connector = createGamePostgresConnector({ url: databaseUrl });
await connector.connect(); await connector.connect();
const prisma = connector.prisma; 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; let committedReadModelChanges: RealtimeReadModelChanges | null = null;
const readModelBaseline = createRealtimeReadModelBaseline(world); const readModelBaseline = createRealtimeReadModelBaseline(world);
@@ -1391,10 +1395,7 @@ export const createDatabaseTurnHooks = async (
if (transaction) { if (transaction) {
await persist(transaction); await persist(transaction);
} else { } else {
await prisma.$transaction( await prisma.$transaction(persist, transactionOptions);
persist,
options?.transactionTimeoutMs ? { timeout: options.transactionTimeoutMs } : undefined
);
} }
const readModelChanges = mergePersistedVisibleLogChanges( const readModelChanges = mergePersistedVisibleLogChanges(
@@ -1425,21 +1426,18 @@ export const createDatabaseTurnHooks = async (
committedReadModelChanges = committed.readModelChanges; committedReadModelChanges = committed.readModelChanges;
}, },
executeCommand: async (requestId, execute) => { executeCommand: async (requestId, execute) => {
const committed = await prisma.$transaction( const committed = await prisma.$transaction(async (transaction) => {
async (transaction) => { const directLogFloor =
const directLogFloor = (
( await transaction.logEntry.findFirst({
await transaction.logEntry.findFirst({ orderBy: { id: 'desc' },
orderBy: { id: 'desc' }, select: { id: true },
select: { id: true }, })
}) )?.id ?? 0;
)?.id ?? 0; const result = await execute({ db: transaction });
const result = await execute({ db: transaction }); const persisted = await persistChanges(transaction, { requestId, result }, directLogFloor);
const persisted = await persistChanges(transaction, { requestId, result }, directLogFloor); return { result, persisted };
return { result, persisted }; }, transactionOptions);
},
options?.transactionTimeoutMs ? { timeout: options.transactionTimeoutMs } : undefined
);
committed.persisted.acknowledge(); committed.persisted.acknowledge();
committedReadModelChanges = committed.persisted.readModelChanges; committedReadModelChanges = committed.persisted.readModelChanges;
return committed.result; return committed.result;