Public: anyone can read this; the crew can change it.

"the merge queue > a gate that never answers is abandoned at the deadline, and the next sweep lands (#3430)" passes every time on a loaded check machine #5627

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

scout/forge:scout/5611-the-merge-queue-a-gate-that-never-answer → main 1 commit fork

  • Merged. scout/5611-the-merge-queue-a-gate-that-never-answer was merged into main as 5edb93d.

Review

Sign in to review this change.
2 files changed +24 −5
src/checks/queue.ts +13 −3
@@ -119,6 +119,10 @@ export const GATE_DEADLINE_MS = 15 * 60_000;
119119
120120 let deadlineMs = GATE_DEADLINE_MS;
121121
122 /** What arms the deadline; tests swap in a clock they fire themselves. */
123 type Schedule = (fire: () => void, ms: number) => ReturnType<typeof setTimeout>;
124 let schedule: Schedule = setTimeout;
125
122126 /**
123127 * The most pulls one candidate carries (#3430): eight keep a gate near one
124128 * full tier and a red's bisection three gates deep. The rest of the line
@@ -140,11 +144,17 @@ export interface QueueOptions {
140144 readonly room?: () => number;
141145 }
142146
143 /** Tests shorten the deadline; the answer puts it back. */
144 export function gateDeadlineForTest(ms: number): () => void {
147 /**
148 * Tests shorten the deadline, or hand `arm` the timer to fire themselves (a
149 * wall-clock deadline races the gate's setup on a loaded machine); the answer
150 * puts both back.
151 */
152 export function gateDeadlineForTest(ms: number, arm?: Schedule): () => void {
145153 deadlineMs = ms;
154 if (arm !== undefined) schedule = arm;
146155 return () => {
147156 deadlineMs = GATE_DEADLINE_MS;
157 schedule = setTimeout;
148158 };
149159 }
150160
@@ -424,7 +434,7 @@ function counted(line: Line, gate: GateCandidate): Gated {
424434 // A gate that never answers is abandoned at the deadline: no verdict,
425435 // and the next sweep forms the line again (#3430).
426436 const cut = new Promise<LandVerdict>((resolve) => {
427 timer = setTimeout(() => {
437 timer = schedule(() => {
428438 log.warn("candidate abandoned", {
429439 repo: line.repoId,
430440 pulls,
test/merge-queue.test.ts +11 −2
@@ -468,7 +468,13 @@ describe("the merge queue", () => {
468468 const repo = await autonomousRepo("never-answers");
469469 const pull = await greenPull(repo, "a.ts");
470470 expect(queueWords(repo.id)).toBe("idle");
471 const restore = gateDeadlineForTest(1500);
471 // The deadline is fired by hand once the gate is reached: a wall clock
472 // would race the gate's setup on a loaded machine.
473 let fire: (() => void) | undefined;
474 const restore = gateDeadlineForTest(1500, (f) => {
475 fire = f;
476 return setTimeout(() => {}, 0);
477 });
472478 const warned: string[] = [];
473479 const warn = console.warn;
474480 console.warn = (line: string) => warned.push(line);
@@ -476,7 +482,10 @@ describe("the merge queue", () => {
476482 let words = "";
477483 try {
478484 lastSignal = undefined;
479 atGate = () => (words = queueWords(repo.id));
485 atGate = () => {
486 words = queueWords(repo.id);
487 fire?.();
488 };
480489 const sweep = sweepGreen(app, repo);
481490 expect(await sweep).toBe(0);
482491 } finally {

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs