Skip to content

Commit 12d5967

Browse files
committed
fix: resolve task TTL even when queue is overridden
When a caller provides a custom queue name (via options.queue), the queue concern returned early without looking up the task's TTL. This caused task-level and config-level TTL to be silently ignored in favor of just the dev default. Now both the locked-worker+custom-queue and non-locked+ custom-queue paths fetch task TTL via minimal select queries. https://claude.ai/code/session_01Swj2TA2crHC29m1ynWwEUN
1 parent 5a68fa0 commit 12d5967

File tree

2 files changed

+38
-2
lines changed

2 files changed

+38
-2
lines changed

apps/webapp/CLAUDE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ Some services (e.g., `cancelTaskRun.server.ts`, `batchTriggerV3.server.ts`) bran
6161

6262
The `triggerTask.server.ts` service is the **highest-throughput code path** in the system. Every API trigger call goes through it. Keep it fast:
6363

64-
- **Do NOT add database queries** to the trigger path. The only acceptable DB query for task defaults (TTL, etc.) is the single existing `backgroundWorkerTask.findFirst()` call with a minimal `select`.
64+
- **Do NOT add database queries** to the trigger path. Task TTL is resolved via the queue concern's existing `backgroundWorkerTask.findFirst()` calls. When a custom queue override is provided, a minimal `select: { ttl: true }` fallback query fetches the task's TTL separately — this is acceptable because custom queue overrides are rare.
6565
- **Two-stage resolution pattern**: Task metadata is resolved in two stages by design:
6666
1. **Trigger time** (`triggerTask.server.ts`): Only TTL is resolved from task defaults. Everything else uses whatever the caller provides.
6767
2. **Dequeue time** (`dequeueSystem.ts`): Full `BackgroundWorkerTask` is loaded and retry config, machine config, maxDuration, etc. are resolved against task defaults.

apps/webapp/app/runEngine/concerns/queues.server.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,13 @@ export class DefaultQueueManager implements QueueManager {
9999
// Use the validated queue name directly
100100
queueName = specifiedQueue.name;
101101
lockedQueueId = specifiedQueue.id;
102+
103+
// Still need task TTL even when queue is overridden
104+
taskTtl = await this.getTaskTtl(
105+
request.taskId,
106+
request.environment.id,
107+
lockedBackgroundWorker.id
108+
);
102109
} else {
103110
// No specific queue name provided, use the default queue for the task on the locked worker
104111
const lockedTask = await this.prisma.backgroundWorkerTask.findFirst({
@@ -183,7 +190,9 @@ export class DefaultQueueManager implements QueueManager {
183190
// Use extractQueueName to handle double-wrapped queue objects
184191
const queueName = extractQueueName(queue);
185192
if (queueName) {
186-
return { queueName };
193+
// Still need task TTL even when queue is overridden
194+
const taskTtl = await this.getTaskTtlForEnvironment(taskId, environment);
195+
return { queueName, taskTtl };
187196
}
188197

189198
const defaultQueueName = `task/${taskId}`;
@@ -233,6 +242,33 @@ export class DefaultQueueManager implements QueueManager {
233242
return { queueName: task.queue.name ?? defaultQueueName, taskTtl: task.ttl };
234243
}
235244

245+
private async getTaskTtl(
246+
taskId: string,
247+
environmentId: string,
248+
workerId: string
249+
): Promise<string | null | undefined> {
250+
const task = await this.prisma.backgroundWorkerTask.findFirst({
251+
where: {
252+
workerId,
253+
runtimeEnvironmentId: environmentId,
254+
slug: taskId,
255+
},
256+
select: { ttl: true },
257+
});
258+
return task?.ttl;
259+
}
260+
261+
private async getTaskTtlForEnvironment(
262+
taskId: string,
263+
environment: AuthenticatedEnvironment
264+
): Promise<string | null | undefined> {
265+
const worker = await findCurrentWorkerFromEnvironment(environment, this.prisma);
266+
if (!worker) {
267+
return undefined;
268+
}
269+
return this.getTaskTtl(taskId, environment.id, worker.id);
270+
}
271+
236272
async validateQueueLimits(
237273
environment: AuthenticatedEnvironment,
238274
queueName: string,

0 commit comments

Comments
 (0)