Skip to content

Commit 2711797

Browse files
committed
fix(webapp): clamp run priority so a large value can't fail run creation
1 parent c72ebf9 commit 2711797

4 files changed

Lines changed: 55 additions & 1 deletion

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
area: webapp
3+
type: fix
4+
---
5+
6+
Triggering a run with a very large `priority` no longer fails. The priority is now capped to the highest supported value instead of erroring out.

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import type {
3333
TriggerTaskServiceResult,
3434
} from "../../v3/services/triggerTask.server";
3535
import { clampMaxDuration } from "../../v3/utils/maxDuration";
36+
import { clampPriorityMs } from "../../v3/utils/priority";
3637
import {
3738
type IdempotencyKeyConcern,
3839
type ClaimedIdempotency,
@@ -887,7 +888,7 @@ export class RunEngineTriggerTaskService {
887888
? clampMaxDuration(args.body.options.maxDuration)
888889
: undefined,
889890
machine: args.body.options?.machine,
890-
priorityMs: args.body.options?.priority ? args.body.options.priority * 1_000 : undefined,
891+
priorityMs: args.body.options?.priority ? clampPriorityMs(args.body.options.priority) : undefined,
891892
queueTimestamp:
892893
args.options.queueTimestamp ??
893894
(args.parentRun && args.body.options?.resumeParentOnCompletion
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { describe, expect, it } from "vitest";
2+
import { clampPriorityMs } from "./priority";
3+
4+
const INT4_MIN = -2_147_483_648;
5+
const INT4_MAX = 2_147_483_647;
6+
7+
describe("clampPriorityMs", () => {
8+
it("converts seconds to milliseconds for in-range values", () => {
9+
expect(clampPriorityMs(10)).toBe(10_000);
10+
expect(clampPriorityMs(0.5)).toBe(500);
11+
});
12+
13+
it("rounds a sub-millisecond fractional priority to an integer", () => {
14+
expect(clampPriorityMs(0.0005)).toBe(1);
15+
expect(clampPriorityMs(0.00049)).toBe(0);
16+
expect(Number.isInteger(clampPriorityMs(0.0005))).toBe(true);
17+
});
18+
19+
it("clamps a value that would overflow INT4 down to the column max", () => {
20+
const priority = 31_536_000;
21+
expect(priority * 1_000).toBeGreaterThan(INT4_MAX);
22+
expect(clampPriorityMs(priority)).toBe(INT4_MAX);
23+
});
24+
25+
it("leaves the largest safe priority untouched", () => {
26+
expect(clampPriorityMs(2_147_483)).toBe(2_147_483_000);
27+
});
28+
29+
it("clamps a large negative priority to the column min", () => {
30+
expect(clampPriorityMs(-3_000_000)).toBe(INT4_MIN);
31+
});
32+
33+
it("keeps every result inside the INT4 range", () => {
34+
for (const priority of [-1e12, -5, -0.3, 0, 0.7, 5, 1234.5678, 1e12]) {
35+
const result = clampPriorityMs(priority);
36+
expect(Number.isInteger(result)).toBe(true);
37+
expect(result).toBeGreaterThanOrEqual(INT4_MIN);
38+
expect(result).toBeLessThanOrEqual(INT4_MAX);
39+
}
40+
});
41+
});
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
const INT4_MIN = -2_147_483_648;
2+
const INT4_MAX = 2_147_483_647;
3+
4+
export function clampPriorityMs(priority: number): number {
5+
return Math.min(Math.max(Math.round(priority * 1_000), INT4_MIN), INT4_MAX);
6+
}

0 commit comments

Comments
 (0)