Skip to content

Commit ad8eead

Browse files
committed
fix(webapp): deploy upserts never clobber concurrent overrides, V2 only for inline default queues
The queue upsert's update carries the override markers in its where clause, so a concurrent override or reset makes the update miss and retry against a fresh read instead of silently overwriting what the operator just set. A queue row is marked concurrencyVersion V2 only when an inline limit compiles into the task's own default queue; shared queues stay V1 whichever code path materializes them.
1 parent 8de004b commit ad8eead

1 file changed

Lines changed: 23 additions & 3 deletions

File tree

‎apps/webapp/app/v3/services/createBackgroundWorker.server.ts‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -469,7 +469,13 @@ async function createWorkerTask(
469469
environment,
470470
prisma,
471471
"QUEUE",
472-
concurrency ? "V2" : "V1"
472+
/**
473+
* V2 marks rows whose limit fields hold the new perKey/total vocabulary. That
474+
* only happens when an inline limit compiles into the task's own default queue;
475+
* a shared queue keeps V1 regardless of task concurrency (which lives in gates
476+
* and LIMIT rows), matching rows materialized from queue() declarations.
477+
*/
478+
concurrency?.inline && !task.queue?.name ? "V2" : "V1"
473479
);
474480
}
475481

@@ -866,9 +872,17 @@ async function upsertWorkerQueueRecord(
866872
const hasOverride = taskQueue.concurrencyLimitOverriddenAt !== null;
867873
const hasTotalOverride = taskQueue.totalConcurrencyLimitOverriddenAt !== null;
868874

875+
/**
876+
* The override markers in the where clause make this an optimistic-concurrency
877+
* update: a concurrent override/reset between the read above and this write
878+
* changes a marker, the update misses (P2025) and the catch below retries with
879+
* a fresh read, so a deploy can never clobber an operator's override.
880+
*/
869881
taskQueue = await prisma.taskQueue.update({
870882
where: {
871883
id: taskQueue.id,
884+
concurrencyLimitOverriddenAt: taskQueue.concurrencyLimitOverriddenAt,
885+
totalConcurrencyLimitOverriddenAt: taskQueue.totalConcurrencyLimitOverriddenAt,
872886
},
873887
data: {
874888
workers: { connect: { id: worker.id } },
@@ -886,8 +900,14 @@ async function upsertWorkerQueueRecord(
886900

887901
return taskQueue;
888902
} catch (error) {
889-
// If the queue already exists, let's try again
890-
if (error instanceof Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
903+
/**
904+
* P2002: the queue was created concurrently. P2025: an override/reset moved a
905+
* marker under the optimistic update. Both re-read and retry.
906+
*/
907+
if (
908+
error instanceof Prisma.PrismaClientKnownRequestError &&
909+
(error.code === "P2002" || error.code === "P2025")
910+
) {
891911
return await upsertWorkerQueueRecord(
892912
queueName,
893913
concurrencyLimit,

0 commit comments

Comments
 (0)