Skip to content

Commit 2cb1c45

Browse files
advaitpaliwalclaude
andcommitted
perf(server): PR sync stops reading pull requests closed over a day ago
Co-authored-by: Claude Opus 5.5 <[email protected]>
1 parent cefb544 commit 2cb1c45

2 files changed

Lines changed: 52 additions & 7 deletions

File tree

‎apps/server/src/orchestration-v2/PullRequestSyncReactor.test.ts‎

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,49 @@ describe("PullRequestSyncReactor", () => {
979979
),
980980
);
981981

982+
it.effect("stops reading a pull request a day after it closed, until a refresh asks", () =>
983+
Effect.scoped(
984+
Effect.gen(function* () {
985+
yield* TestClock.setTime(Date.parse(NOW));
986+
const closed = (closedAt: string | null) => ({ state: "closed" as const, closedAt });
987+
const fixture = yield* makeHarness({
988+
snapshot: makeSnapshot([
989+
makeThread("closed", {
990+
pullRequests: [
991+
makeLink(1, closed("2026-08-20T00:00:00.000Z")),
992+
makeLink(2, closed("2026-08-26T00:00:00.000Z")),
993+
makeLink(3, closed("2026-08-28T11:00:00.000Z")),
994+
makeLink(4, closed(null)),
995+
],
996+
}),
997+
]),
998+
summary: (input) =>
999+
Effect.succeed(makeSummary(input, { state: "closed", closedAt: NOW })),
1000+
});
1001+
const reads = Ref.get(fixture.summaryCalls).pipe(
1002+
Effect.map((calls) => calls.map((call) => call.number).toSorted()),
1003+
);
1004+
1005+
yield* Effect.gen(function* () {
1006+
const reactor = yield* startAndSweep(fixture);
1007+
// Closed within the day, or with no close time, keeps the fifteen-minute cadence.
1008+
assert.deepStrictEqual(yield* reads, [3, 4]);
1009+
for (let index = 0; index < 15; index += 1) yield* sweepAgain(fixture, reactor);
1010+
assert.deepStrictEqual(yield* reads, [3, 3, 4, 4]);
1011+
1012+
yield* reactor.requestSync({
1013+
host: "github.com",
1014+
repository: "owner/repository",
1015+
number: 1,
1016+
});
1017+
yield* Queue.take(fixture.snapshotReads);
1018+
yield* reactor.drain;
1019+
assert.deepStrictEqual(yield* reads, [1, 3, 3, 4, 4]);
1020+
}).pipe(Effect.provide(fixture.layer));
1021+
}),
1022+
),
1023+
);
1024+
9821025
it.effect("re-reads a merged pull request until the host supplies its merge time", () =>
9831026
Effect.scoped(
9841027
Effect.gen(function* () {

‎apps/server/src/orchestration-v2/PullRequestSyncReactor.ts‎

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ const SLOW_SYNC_INTERVAL_MS = 15 * 60 * 1_000;
4444
// requested refreshes, watches and a host CLI's merge command still read it at once.
4545
const QUIET_AFTER_MS = 30 * 60 * 1_000;
4646
const QUIET_SYNC_INTERVAL_MS = 5 * 60 * 1_000;
47+
// A pull request closed this long ago is rarely reopened, so the sweep stops reading it, as it
48+
// does merged ones. A reader that sees it open, or a requested refresh, still reads it at once.
49+
const CLOSED_FINAL_AFTER_MS = 24 * 60 * 60 * 1_000;
4750

4851
const isChangeRequestCloseCommand = (command: string) =>
4952
sourceControlDefinitions.definitions.some(
@@ -351,13 +354,12 @@ export const make = Effect.gen(function* () {
351354
if (entries.some((entry) => entry.link.snapshot === null)) return true;
352355
const active = entries.filter((entry) => isUnsettled(entry.thread));
353356
// Merged snapshots without mergedAt cannot settle threads; reread slowly until supplied.
354-
if (
355-
active.every(
356-
(entry) => entry.link.snapshot?.state === "merged" && entry.link.snapshot.mergedAt != null,
357-
)
358-
) {
359-
return false;
360-
}
357+
const isFinal = ({ link: { snapshot } }: LinkEntry) =>
358+
snapshot?.state === "merged"
359+
? snapshot.mergedAt != null
360+
: snapshot?.state === "closed" &&
361+
nowMs - Date.parse(snapshot.closedAt ?? "") >= CLOSED_FINAL_AFTER_MS;
362+
if (active.every(isFinal)) return false;
361363
const last = lastSyncedAt.get(key);
362364
const sinceLastMs = last === undefined ? Number.POSITIVE_INFINITY : nowMs - last;
363365
const open = active.filter((entry) => entry.link.snapshot?.state === "open");

0 commit comments

Comments
 (0)