Skip to content

Commit e5f9dd1

Browse files
committed
fix(webapp): use prisma writer for post-race re-read of session row in sessionRunManager
The lost-race re-read in ensureRunForSession and swapSessionRun reads the Session row that the winner just wrote on the writer. Reading from $replica could return pre-race state and either (1) cause ensureRunForSession to recurse with a stale currentRunVersion, fail the next claim, and waste runs until max-attempts; or (2) cause swapSessionRun to return swapped: false with the calling run's own id, misleading the caller into thinking it is still authoritative.
1 parent c0e87bf commit e5f9dd1

1 file changed

Lines changed: 11 additions & 2 deletions

File tree

apps/webapp/app/services/realtime/sessionRunManager.server.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -153,7 +153,11 @@ export async function ensureRunForSession(
153153
});
154154
});
155155

156-
const fresh = await $replica.session.findFirst({
156+
// Read-after-write: the winner just wrote `currentRunId` /
157+
// `currentRunVersion` on the writer. Reading from `$replica` could
158+
// return pre-race state and cause us to recurse with the same stale
159+
// version, losing the next claim, until we exhaust max attempts.
160+
const fresh = await prisma.session.findFirst({
157161
where: { id: session.id },
158162
select: {
159163
id: true,
@@ -327,7 +331,12 @@ export async function swapSessionRun(
327331
});
328332
});
329333

330-
const fresh = await $replica.session.findFirst({
334+
// Read-after-write: the winner's swap was just committed on the
335+
// writer. A replica read could return the pre-swap `currentRunId`
336+
// (often `callingRunId` itself), which would tell the caller it is
337+
// still the canonical run when in fact a different run has taken
338+
// over.
339+
const fresh = await prisma.session.findFirst({
331340
where: { id: session.id },
332341
select: { currentRunId: true },
333342
});

0 commit comments

Comments
 (0)