refactor: remove obsolete external object batch refresh entrypoints

Exercise lease, selection, and recovery behavior through the registered scheduler owner.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-30 18:09:41 -05:00
1 parent 4771986772
commit 4e97daafa0
5 files changed
+43 -95

No files matched your search

@@ -1,4 +1,5 @@
import { randomUUID } from "node:crypto";
import { createDeliveryWorkCoordinator } from "../services/delivery-work-coordinator.js";
import { afterAll, afterEach, beforeAll, describe, expect, it, vi } from "vitest";
import { eq } from "drizzle-orm";
import {
@@ -733,6 +734,18 @@ describeEmbeddedPostgres("externalObjectService", () => {
await tempDb?.cleanup();
});
async function runRefreshWork(service: ReturnType<typeof externalObjectService>) {
const errors: unknown[] = [];
const coordinator = createDeliveryWorkCoordinator({ owner: db, canRun: () => true,
onError: error => errors.push(error) });
try {
await service.registerRefreshWork(coordinator, () => true).ready;
expect(errors).toEqual([]);
} finally {
await coordinator.stop();
}
}
async function createIssue(companyId = randomUUID()) {
const issueId = randomUUID();
await db.insert(companies).values({
@@ -882,9 +895,9 @@ describeEmbeddedPostgres("externalObjectService", () => {
expect(object.nextRefreshAt).toBeInstanceOf(Date);
const refreshed = await svc.refreshDueObjects(companyId, 50, new Date(Date.now() + 1_000));
await runRefreshWork(svc);
expect(refreshed).toHaveLength(1);
expect((await db.select().from(externalObjects))[0]?.lastResolvedAt).toBeInstanceOf(Date);
expect(resolve).toHaveBeenCalledTimes(1);
});
@@ -921,15 +934,13 @@ describeEmbeddedPostgres("externalObjectService", () => {
await svc.syncIssue(issueId);
const object = await db.select().from(externalObjects).then((rows) => rows[0]!);
const dueRefresh = svc.refreshDueObjects(companyId, 50, new Date(Date.now() + 1_000));
const dueRefresh = runRefreshWork(svc);
await resolverStarted;
const manualRefresh = svc.refreshObject(object.id, { companyId, force: true });
finishResolver();
const [dueResults, manualResult] = await Promise.all([dueRefresh, manualRefresh]);
const [, manualResult] = await Promise.all([dueRefresh, manualRefresh]);
expect(dueResults).toHaveLength(1);
expect(dueResults[0]?.refreshed).toBe(true);
expect(manualResult.refreshed).toBe(true);
expect(manualResult.object.statusLabel).toBe("Open");
expect(resolve).toHaveBeenCalledTimes(1);
@@ -969,14 +980,12 @@ describeEmbeddedPostgres("externalObjectService", () => {
await scheduledService.syncIssue(issueId);
const object = await db.select().from(externalObjects).then((rows) => rows[0]!);
const dueRefresh = scheduledService.refreshDueObjects(companyId, 50, new Date(Date.now() + 1_000));
const dueRefresh = runRefreshWork(scheduledService);
await resolverStarted;
const manualRefresh = await manualService.refreshObject(object.id, { companyId, force: true });
finishResolver();
const dueResults = await dueRefresh;
await dueRefresh;
expect(dueResults).toHaveLength(1);
expect(dueResults[0]?.refreshed).toBe(true);
expect(manualRefresh.refreshed).toBe(false);
expect(manualRefresh.reason).toBe("refresh_in_progress");
expect(manualRefresh.object).not.toHaveProperty("refreshToken");
@@ -1032,7 +1041,7 @@ describeEmbeddedPostgres("externalObjectService", () => {
const object = await db.select().from(externalObjects).then((rows) => rows[0]!);
const claimedAt = new Date(Date.now() + 1_000);
const dueRefresh = scheduledService.refreshDueObjects(companyId, 50, claimedAt);
const dueRefresh = runRefreshWork(scheduledService);
await resolverStarted;
const replacementResult = await replacementService.refreshObject(object.id, {
companyId,
@@ -1040,11 +1049,10 @@ describeEmbeddedPostgres("externalObjectService", () => {
now: new Date(claimedAt.getTime() + 301_000),
});
finishResolver();
const dueResults = await dueRefresh;
await dueRefresh;
const finalObject = await db.select().from(externalObjects).then((rows) => rows[0]!);
expect(replacementResult.refreshed).toBe(true);
expect(dueResults[0]).toMatchObject({ refreshed: false, reason: "refresh_superseded" });
expect(finalObject.statusLabel).toBe("Closed");
expect(finalObject.refreshStartedAt).toBeNull();
expect(finalObject.refreshToken).toBeNull();
@@ -1078,9 +1086,7 @@ describeEmbeddedPostgres("externalObjectService", () => {
await svc.syncIssue(active.issueId);
await svc.syncIssue(paused.issueId);
const result = await svc.refreshDueObjectsForActiveCompanies(50, new Date(Date.now() + 1_000));
expect(result).toEqual({ companies: 1, checked: 1, refreshed: 1 });
await runRefreshWork(svc);
expect(resolve).toHaveBeenCalledTimes(1);
const rows = await db.select().from(externalObjects);
const activeObject = rows.find((row) => row.companyId === active.companyId);
@@ -1139,9 +1145,8 @@ describeEmbeddedPostgres("externalObjectService", () => {
.set({ nextRefreshAt: new Date(0) })
.where(eq(externalObjects.id, object.id));
const refreshed = await svc.refreshDueObjects(companyId);
await runRefreshWork(svc);
expect(refreshed).toEqual([]);
expect(resolve).toHaveBeenCalledTimes(1);
});
@@ -1184,7 +1189,7 @@ describeEmbeddedPostgres("externalObjectService", () => {
});
it("re-checks previously frozen GitHub not-found objects so they can self-heal", async () => {
const { companyId } = await createIssue();
const { companyId, issueId } = await createIssue();
const canonical = canonicalizeExternalObjectUrl("https://github.com/acme/app/pull/42");
if (!canonical) throw new Error("expected canonical url");
const inserted = await db.insert(externalObjects).values({
@@ -1225,9 +1230,10 @@ describeEmbeddedPostgres("externalObjectService", () => {
const svc = externalObjectService(db, { resolvers: [resolver], github: false });
expect(object.isTerminal).toBe(true);
const refreshed = await svc.refreshDueObjects(companyId);
expect(refreshed).toHaveLength(1);
expect(refreshed[0]?.refreshed).toBe(true);
const [linked] = await db.select().from(externalObjects).where(eq(externalObjects.companyId, companyId));
await db.insert(externalObjectMentions).values({ companyId, sourceIssueId: issueId,
sourceKind: "description", objectId: linked!.id });
await runRefreshWork(svc);
const updated = await db.select().from(externalObjects).then((rows) => rows[0]!);
expect(updated.statusLabel).toBe("Open");
@@ -1236,7 +1242,7 @@ describeEmbeddedPostgres("externalObjectService", () => {
});
it("does not re-check probe-verified GitHub not-found objects (deleted references are terminal)", async () => {
const { companyId } = await createIssue();
const { companyId, issueId } = await createIssue();
const canonical = canonicalizeExternalObjectUrl("https://github.com/acme/app/pull/42");
if (!canonical) throw new Error("expected canonical url");
await db.insert(externalObjects).values({
@@ -1273,14 +1279,16 @@ describeEmbeddedPostgres("externalObjectService", () => {
};
const svc = externalObjectService(db, { resolvers: [resolver], github: false });
const refreshed = await svc.refreshDueObjects(companyId);
const [linked] = await db.select().from(externalObjects).where(eq(externalObjects.companyId, companyId));
await db.insert(externalObjectMentions).values({ companyId, sourceIssueId: issueId,
sourceKind: "description", objectId: linked!.id });
await runRefreshWork(svc);
expect(refreshed).toEqual([]);
expect(resolver.resolve).not.toHaveBeenCalled();
});
it("does not re-check terminal objects that are not GitHub not-found verdicts", async () => {
const { companyId } = await createIssue();
const { companyId, issueId } = await createIssue();
const canonical = canonicalizeExternalObjectUrl("https://github.com/acme/app/pull/42");
if (!canonical) throw new Error("expected canonical url");
await db.insert(externalObjects).values({
@@ -1316,9 +1324,11 @@ describeEmbeddedPostgres("externalObjectService", () => {
};
const svc = externalObjectService(db, { resolvers: [resolver], github: false });
const refreshed = await svc.refreshDueObjects(companyId);
const [linked] = await db.select().from(externalObjects).where(eq(externalObjects.companyId, companyId));
await db.insert(externalObjectMentions).values({ companyId, sourceIssueId: issueId,
sourceKind: "description", objectId: linked!.id });
await runRefreshWork(svc);
expect(refreshed).toEqual([]);
expect(resolver.resolve).not.toHaveBeenCalled();
});