Skip to content

Commit aec7059

Browse files
committed
fix: eliminate extra DB query for task TTL at trigger time
Piggyback on existing BackgroundWorkerTask query in queue resolution instead of adding a separate findFirst in the hot trigger path. https://claude.ai/code/session_01Swj2TA2crHC29m1ynWwEUN
1 parent 424238a commit aec7059

File tree

3 files changed

+36
-35
lines changed

3 files changed

+36
-35
lines changed

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

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ export class DefaultQueueManager implements QueueManager {
7373
): Promise<QueueProperties> {
7474
let queueName: string;
7575
let lockedQueueId: string | undefined;
76+
let taskTtl: string | null | undefined;
7677

7778
// Determine queue name based on lockToVersion and provided options
7879
if (lockedBackgroundWorker) {
@@ -134,6 +135,7 @@ export class DefaultQueueManager implements QueueManager {
134135
// Use the task's default queue name
135136
queueName = lockedTask.queue.name;
136137
lockedQueueId = lockedTask.queue.id;
138+
taskTtl = lockedTask.ttl;
137139
}
138140
} else {
139141
// Task is not locked to a specific version, use regular logic
@@ -145,7 +147,9 @@ export class DefaultQueueManager implements QueueManager {
145147
}
146148

147149
// Get queue name using the helper for non-locked case (handles provided name or finds default)
148-
queueName = await this.getQueueName(request);
150+
const taskInfo = await this.getTaskQueueInfo(request);
151+
queueName = taskInfo.queueName;
152+
taskTtl = taskInfo.taskTtl;
149153
}
150154

151155
// Sanitize the final determined queue name once
@@ -161,17 +165,25 @@ export class DefaultQueueManager implements QueueManager {
161165
return {
162166
queueName,
163167
lockedQueueId,
168+
taskTtl,
164169
};
165170
}
166171

167172
async getQueueName(request: TriggerTaskRequest): Promise<string> {
173+
const result = await this.getTaskQueueInfo(request);
174+
return result.queueName;
175+
}
176+
177+
private async getTaskQueueInfo(
178+
request: TriggerTaskRequest
179+
): Promise<{ queueName: string; taskTtl?: string | null }> {
168180
const { taskId, environment, body } = request;
169181
const { queue } = body.options ?? {};
170182

171183
// Use extractQueueName to handle double-wrapped queue objects
172184
const queueName = extractQueueName(queue);
173185
if (queueName) {
174-
return queueName;
186+
return { queueName };
175187
}
176188

177189
const defaultQueueName = `task/${taskId}`;
@@ -185,7 +197,7 @@ export class DefaultQueueManager implements QueueManager {
185197
environmentId: environment.id,
186198
});
187199

188-
return defaultQueueName;
200+
return { queueName: defaultQueueName };
189201
}
190202

191203
const task = await this.prisma.backgroundWorkerTask.findFirst({
@@ -205,7 +217,7 @@ export class DefaultQueueManager implements QueueManager {
205217
environmentId: environment.id,
206218
});
207219

208-
return defaultQueueName;
220+
return { queueName: defaultQueueName };
209221
}
210222

211223
if (!task.queue) {
@@ -215,10 +227,10 @@ export class DefaultQueueManager implements QueueManager {
215227
queueConfig: task.queueConfig,
216228
});
217229

218-
return defaultQueueName;
230+
return { queueName: defaultQueueName, taskTtl: task.ttl };
219231
}
220232

221-
return task.queue.name ?? defaultQueueName;
233+
return { queueName: task.queue.name ?? defaultQueueName, taskTtl: task.ttl };
222234
}
223235

224236
async validateQueueLimits(

apps/webapp/app/runEngine/services/triggerTask.server.ts

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -190,31 +190,6 @@ export class RunEngineTriggerTaskService {
190190
}
191191
}
192192

193-
// Resolve TTL with precedence: per-trigger > task-level > dev default
194-
let ttl: string | undefined;
195-
196-
if (body.options?.ttl !== undefined) {
197-
// Per-trigger TTL takes highest priority
198-
ttl =
199-
typeof body.options.ttl === "number"
200-
? stringifyDuration(body.options.ttl)
201-
: body.options.ttl;
202-
} else {
203-
// Look up task-level TTL default from BackgroundWorkerTask
204-
const taskDefaults = await this.prisma.backgroundWorkerTask.findFirst({
205-
where: {
206-
slug: taskId,
207-
projectId: environment.projectId,
208-
runtimeEnvironmentId: environment.id,
209-
},
210-
select: { ttl: true },
211-
orderBy: { createdAt: "desc" },
212-
});
213-
214-
ttl =
215-
taskDefaults?.ttl ?? (environment.type === "DEVELOPMENT" ? "10m" : undefined);
216-
}
217-
218193
// Get parent run if specified
219194
const parentRun = body.options?.parentRunId
220195
? await this.prisma.taskRun.findFirst({
@@ -270,10 +245,23 @@ export class RunEngineTriggerTaskService {
270245
})
271246
: undefined;
272247

273-
const { queueName, lockedQueueId } = await this.queueConcern.resolveQueueProperties(
274-
triggerRequest,
275-
lockedToBackgroundWorker ?? undefined
276-
);
248+
const { queueName, lockedQueueId, taskTtl } =
249+
await this.queueConcern.resolveQueueProperties(
250+
triggerRequest,
251+
lockedToBackgroundWorker ?? undefined
252+
);
253+
254+
// Resolve TTL with precedence: per-trigger > task-level > dev default
255+
let ttl: string | undefined;
256+
257+
if (body.options?.ttl !== undefined) {
258+
ttl =
259+
typeof body.options.ttl === "number"
260+
? stringifyDuration(body.options.ttl)
261+
: body.options.ttl;
262+
} else {
263+
ttl = taskTtl ?? (environment.type === "DEVELOPMENT" ? "10m" : undefined);
264+
}
277265

278266
if (!options.skipChecks) {
279267
const queueSizeGuard = await this.queueConcern.validateQueueLimits(

apps/webapp/app/runEngine/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ export type QueueValidationResult =
4848
export type QueueProperties = {
4949
queueName: string;
5050
lockedQueueId?: string;
51+
taskTtl?: string | null;
5152
};
5253

5354
export type LockedBackgroundWorker = Pick<

0 commit comments

Comments
 (0)