Skip to content

Commit 32cd75d

Browse files
committed
fix(queue): complete #5021's cron-path fix -- the fan-out dispatcher itself was still isRegistered-gated
#5021 retargeted the two downstream entry points (backfillRegisteredRepositories, enqueueRepositoryOpenDataBackfill) from isRegistered to isInstalled, but never touched the actual candidate- selection step for the periodic (30-min) cron sweep: processJob's "backfill-registered-repos" no-repoFullName branch in job-dispatch.ts still filtered listRepositories() on isRegistered before ever dispatching a per-repo job. An installed-but-not-subnet-registered repo therefore never got a per-repo backfill job enqueued for it in the first place -- #5021's fix never actually took effect on the real cron path, only on direct/API- triggered single-repo calls. Found via a full-codebase audit of remaining isRegistered call sites after #5021 merged. Part of #5016
1 parent 21d13b2 commit 32cd75d

3 files changed

Lines changed: 39 additions & 3 deletions

File tree

src/queue/job-dispatch.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,13 @@ export async function processJob(env: Env, message: JobMessage): Promise<void> {
7575
return;
7676
case "backfill-registered-repos":
7777
if (!message.repoFullName && message.requestedBy !== "test") {
78+
// #5021 retargeted the two downstream entry points (backfillRegisteredRepositories,
79+
// enqueueRepositoryOpenDataBackfill) from isRegistered to isInstalled, but this cron-scheduled
80+
// fan-out is the actual candidate-selection step for the periodic sweep, and was left on
81+
// isRegistered -- an installed-but-not-subnet-registered repo never got a per-repo job dispatched
82+
// for it in the first place, so #5021's fix never took effect on the real 30-min cron path.
7883
const repositories = (await listRepositories(env)).filter(
79-
(repo) => repo.isRegistered,
84+
(repo) => repo.isInstalled,
8085
);
8186
if (repositories.length > 0) {
8287
const delayStepSeconds =

test/unit/queue-2.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3131,11 +3131,15 @@ describe("queue processors", () => {
31313131
"we-promise/sure": { emission_share: 0.02, issue_discovery_share: 0, label_multipliers: {}, trusted_label_pipeline: false },
31323132
},
31333133
{ kind: "raw-github", url: "fixture://registry" },
3134-
"2026-05-25T00:00:00.000Z",
3134+
"2026-05-23T00:00:00.000Z",
31353135
),
31363136
);
3137+
// The cron fan-out now gates on isInstalled, not isRegistered.
3138+
await upsertRepositoryFromGitHub(env, { name: "gittensory", full_name: "JSONbored/gittensory", private: true, owner: { login: "JSONbored" } }, 9408);
3139+
await upsertRepositoryFromGitHub(env, { name: "sure", full_name: "we-promise/sure", private: true, owner: { login: "we-promise" } }, 9409);
31373140
vi.stubGlobal("fetch", async (input: RequestInfo | URL) => {
31383141
const url = input.toString();
3142+
if (url.includes("/access_tokens")) return Response.json({ token: "installation-token" });
31393143
if (url === "https://api.github.com/graphql") {
31403144
return Response.json({
31413145
data: {

test/unit/queue.test.ts

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -678,9 +678,12 @@ describe("queue processors", () => {
678678
"we-promise/sure": { emission_share: 0.02, issue_discovery_share: 0, label_multipliers: {}, trusted_label_pipeline: false },
679679
},
680680
{ kind: "raw-github", url: "fixture://registry" },
681-
"2026-05-25T00:00:00.000Z",
681+
"2026-05-23T00:00:00.000Z",
682682
),
683683
);
684+
// The cron fan-out now gates on isInstalled, not isRegistered (completes #5021's real cron-path fix).
685+
await upsertRepositoryFromGitHub(env, { name: "gittensory", full_name: "JSONbored/gittensory", private: true, owner: { login: "JSONbored" } }, 9405);
686+
await upsertRepositoryFromGitHub(env, { name: "sure", full_name: "we-promise/sure", private: true, owner: { login: "we-promise" } }, 9406);
684687

685688
await processJob(env, { type: "backfill-registered-repos", requestedBy: "api", force: true, mode: "full" });
686689

@@ -691,6 +694,30 @@ describe("queue processors", () => {
691694
expect(await listRepoSyncStates(env)).toEqual([]);
692695
});
693696

697+
it("#cron-backfill-dispatch-isinstalled: cron fan-out includes an installed-but-not-registered repo and excludes a registered-but-not-installed one", async () => {
698+
const sent: import("../../src/types").JobMessage[] = [];
699+
const env = createTestEnv({
700+
JOBS: {
701+
async send(message: import("../../src/types").JobMessage) {
702+
sent.push(message);
703+
},
704+
} as unknown as Queue,
705+
});
706+
await persistRegistrySnapshot(
707+
env,
708+
normalizeRegistryPayload(
709+
{ "acme/registered-only": { emission_share: 0.01, issue_discovery_share: 0, label_multipliers: {}, trusted_label_pipeline: false } },
710+
{ kind: "raw-github", url: "fixture://registry" },
711+
"2026-05-23T00:00:00.000Z",
712+
),
713+
);
714+
await upsertRepositoryFromGitHub(env, { name: "installed-only", full_name: "acme/installed-only", private: false, owner: { login: "acme" } }, 9407);
715+
716+
await processJob(env, { type: "backfill-registered-repos", requestedBy: "api" });
717+
718+
expect(sent).toEqual([expect.objectContaining({ type: "backfill-registered-repos", repoFullName: "acme/installed-only" })]);
719+
});
720+
694721
it("falls back to inline all-repo backfill when no registered repositories exist", async () => {
695722
const sent: import("../../src/types").JobMessage[] = [];
696723
const env = createTestEnv({

0 commit comments

Comments
 (0)