Repository navigation
improvement(file-search): only start the dispatcher when there is dispatch work - #8714
waleedlatif1 wants to merge 1 commit into
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
| export async function hasWorkspaceFileSearchDispatchWork(now: Date): Promise<boolean> { | ||
| const [cursor] = await db | ||
| .select({ completedAt: workspaceFileSearchBackfill.completedAt }) | ||
| .from(workspaceFileSearchBackfill) | ||
| .where(eq(workspaceFileSearchBackfill.id, BACKFILL_CURSOR_ID)) | ||
| .limit(1) |
There was a problem hiding this comment.
The new database reads run before enqueueing without setting query or lock timeouts. If a table lock or slow query holds either read past the cron request's 60-second limit, hasDispatchWork never reaches its catch and no dispatcher starts. Run the check in a short, timeout-bound transaction so a stalled check can fall back to dispatching.
| expect(plan).toContain('workspace_file_search_build_cleanup_idx') | ||
| expect(plan).toMatch(/using workspace_file_search_revision_workspace_id_dispatched_at_idx/) | ||
| expect(plan).not.toMatch(/Seq Scan/) |
There was a problem hiding this comment.
The new plan test expects a fixture index on (workspace_id, dispatched_at), but production's workspace_file_search_revision_active_idx uses (dispatched_at, workspace_id). It therefore does not check the production index promised by the test. Create that index in the fixture and assert its name. Also distinguish forced index use from the plan PostgreSQL would normally choose.
| vi.mock('@/lib/workspace-files/search/index-state', async (importOriginal) => ({ | ||
| ...(await importOriginal<typeof import('@/lib/workspace-files/search/index-state')>()), | ||
| cleanupFileSearchBuilds: vi.fn().mockResolvedValue(0), |
There was a problem hiding this comment.
The new partial mock uses importOriginal. The testing guide explicitly says never to use vi.importActual() or importOriginal to build a partial mock; use the central mock instead. This loads the real module and its imports just to retain fileSearchBuildExpired. Keep the real module unmocked for this integration test, or use a faithful shared mock. This repository requirement must be satisfied before merging.
Context Used: CLAUDE.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| triggered: true, | ||
| backend: 'trigger-dev', | ||
| }) | ||
| expect(mockTrigger).toHaveBeenCalledTimes(1) |
There was a problem hiding this comment.
The new failure-path test proves dispatch by asserting that mockTrigger was called. CLAUDE.md explicitly forbids tests that assert mock calls. Check the actual enqueue boundary and its accepted result instead, so the test catches a failed handoff rather than just a call to a spy. This repository requirement must be satisfied before merging.
Context Used: CLAUDE.md (source)
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
Folded into #8713 so the outbox and file-search gates can share one scheduled-pass helper (no change to the file-search gate itself). |
Summary
workspace-file-search-dispatchcron started a Trigger.dev run every tick even when nothing needed dispatching.enqueueWorkspaceFileSearchDispatchnow checks first (same pattern as/api/cron/knowledge-projection) and starts a run only if one of the dispatcher's own phases would act:isBackfillPageDue, now shared withseedBackfillPagefileSearchBuildExpired, now shared withcleanupFileSearchBuildsstaleClaim, now shared withreapStaleClaimstriggered: falseon an idle tick (202 when it dispatches)enqueue-dispatch.tsnow usesimport typefor the task instead of a runtimeimport()used only for its typedb:pushdon't install the mark-pending trigger and rely on that walkType of Change
Testing
dispatcher.integration.ts): each work leg reports work (queued workspace, expired build, claim past stale window, claim past handoff deadline, backfill never completed / due, missing cursor); the idle case reports no work ANDprepareWorkspaceFileSearchDispatchdoes nothing on the same data; EXPLAIN asserts no Seq Scanenqueue-dispatch.test.ts, both backends): no work → no run; check error → runbun run lint,bun run type-check,bun run check:audits— green; 15 files / 191 tests inlib/workspace-files/search+ cron routesChecklist
test-auditauthoring gate)