From 32cd75de4da2c03ef7c0b3ae56221dc17415e505 Mon Sep 17 00:00:00 2001 From: JSONbored <49853598+JSONbored@users.noreply.github.com> Date: Mon, 13 Jul 2026 21:43:21 -0700 Subject: [PATCH] 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 --- src/queue/job-dispatch.ts | 7 ++++++- test/unit/queue-2.test.ts | 6 +++++- test/unit/queue.test.ts | 29 ++++++++++++++++++++++++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/queue/job-dispatch.ts b/src/queue/job-dispatch.ts index 9a97bc780c..5ce7ba6d81 100644 --- a/src/queue/job-dispatch.ts +++ b/src/queue/job-dispatch.ts @@ -75,8 +75,13 @@ export async function processJob(env: Env, message: JobMessage): Promise { return; case "backfill-registered-repos": if (!message.repoFullName && message.requestedBy !== "test") { + // #5021 retargeted the two downstream entry points (backfillRegisteredRepositories, + // enqueueRepositoryOpenDataBackfill) from isRegistered to isInstalled, but this cron-scheduled + // fan-out is the actual candidate-selection step for the periodic sweep, and was left on + // isRegistered -- an installed-but-not-subnet-registered repo never got a per-repo job dispatched + // for it in the first place, so #5021's fix never took effect on the real 30-min cron path. const repositories = (await listRepositories(env)).filter( - (repo) => repo.isRegistered, + (repo) => repo.isInstalled, ); if (repositories.length > 0) { const delayStepSeconds = diff --git a/test/unit/queue-2.test.ts b/test/unit/queue-2.test.ts index 428767ae3a..503612bb7e 100644 --- a/test/unit/queue-2.test.ts +++ b/test/unit/queue-2.test.ts @@ -3131,11 +3131,15 @@ describe("queue processors", () => { "we-promise/sure": { emission_share: 0.02, issue_discovery_share: 0, label_multipliers: {}, trusted_label_pipeline: false }, }, { kind: "raw-github", url: "fixture://registry" }, - "2026-05-25T00:00:00.000Z", + "2026-05-23T00:00:00.000Z", ), ); + // The cron fan-out now gates on isInstalled, not isRegistered. + await upsertRepositoryFromGitHub(env, { name: "gittensory", full_name: "JSONbored/gittensory", private: true, owner: { login: "JSONbored" } }, 9408); + await upsertRepositoryFromGitHub(env, { name: "sure", full_name: "we-promise/sure", private: true, owner: { login: "we-promise" } }, 9409); vi.stubGlobal("fetch", async (input: RequestInfo | URL) => { const url = input.toString(); + if (url.includes("/access_tokens")) return Response.json({ token: "installation-token" }); if (url === "https://api.github.com/graphql") { return Response.json({ data: { diff --git a/test/unit/queue.test.ts b/test/unit/queue.test.ts index e8e9ac5ed8..3d9d555935 100644 --- a/test/unit/queue.test.ts +++ b/test/unit/queue.test.ts @@ -678,9 +678,12 @@ describe("queue processors", () => { "we-promise/sure": { emission_share: 0.02, issue_discovery_share: 0, label_multipliers: {}, trusted_label_pipeline: false }, }, { kind: "raw-github", url: "fixture://registry" }, - "2026-05-25T00:00:00.000Z", + "2026-05-23T00:00:00.000Z", ), ); + // The cron fan-out now gates on isInstalled, not isRegistered (completes #5021's real cron-path fix). + await upsertRepositoryFromGitHub(env, { name: "gittensory", full_name: "JSONbored/gittensory", private: true, owner: { login: "JSONbored" } }, 9405); + await upsertRepositoryFromGitHub(env, { name: "sure", full_name: "we-promise/sure", private: true, owner: { login: "we-promise" } }, 9406); await processJob(env, { type: "backfill-registered-repos", requestedBy: "api", force: true, mode: "full" }); @@ -691,6 +694,30 @@ describe("queue processors", () => { expect(await listRepoSyncStates(env)).toEqual([]); }); + it("#cron-backfill-dispatch-isinstalled: cron fan-out includes an installed-but-not-registered repo and excludes a registered-but-not-installed one", async () => { + const sent: import("../../src/types").JobMessage[] = []; + const env = createTestEnv({ + JOBS: { + async send(message: import("../../src/types").JobMessage) { + sent.push(message); + }, + } as unknown as Queue, + }); + await persistRegistrySnapshot( + env, + normalizeRegistryPayload( + { "acme/registered-only": { emission_share: 0.01, issue_discovery_share: 0, label_multipliers: {}, trusted_label_pipeline: false } }, + { kind: "raw-github", url: "fixture://registry" }, + "2026-05-23T00:00:00.000Z", + ), + ); + await upsertRepositoryFromGitHub(env, { name: "installed-only", full_name: "acme/installed-only", private: false, owner: { login: "acme" } }, 9407); + + await processJob(env, { type: "backfill-registered-repos", requestedBy: "api" }); + + expect(sent).toEqual([expect.objectContaining({ type: "backfill-registered-repos", repoFullName: "acme/installed-only" })]); + }); + it("falls back to inline all-repo backfill when no registered repositories exist", async () => { const sent: import("../../src/types").JobMessage[] = []; const env = createTestEnv({