refactor(jobs): convert jobs API requests to server functions#1008
Merged
igboyes merged 6 commits intoJun 1, 2026
Merged
Conversation
Move the read-only jobs list and detail queries off the legacy superagent API client and onto TanStack Start server functions following the data.ts -> functions.ts layering. - add a Drizzle mirror of the jobs table and its resource junction tables - data.ts replicates the Python find() counts/pagination and get() args reconstruction, porting compute_progress - functions.ts validates input with zod and maps JobNotFoundError to 404 - queries.ts keeps its query keys, cache seeding, and zod parsing intact - mock the jobs server functions at the boundary in tests, as for users
data.ts owns the canonical JOB_STATES tuple and derives JobState from it; functions.ts builds its zod enum with z.enum(JOB_STATES) instead of re-spelling the literals.
build_index jobs carry an index_id but not the reference id, so JobArgs rendered Reference and Index links pointing at /refs/undefined. Resolve the reference from the index in JobDetail and inject it into the job args before rendering, keeping both fetches under one loading gate so the rows do not pop in. useFetchIndex gains an opt-out so non-index jobs skip the request. Adds a JobDetail test covering the link derivation.
Server-function errors cross the RPC boundary as plain Errors with only name/message preserved — the HTTP status from setResponseStatus is not attached. Match UnauthorizedError / ForbiddenError by name so a 401/403 (e.g. after logout) rejects immediately instead of retrying ~4× while the screen sits blank before the route bounces to /login.
There was a problem hiding this comment.
Code Review
This pull request migrates the jobs feature to use TanStack Start server functions and Postgres (via Drizzle ORM) instead of direct API client calls to the legacy Python API. It introduces the read-only database schema for jobs, implements the findJobs and getJob server functions, and updates the UI components and routing logic to integrate these changes. Feedback on the changes highlights a critical issue where the rethrowAsHttp helper (wrapped in createServerOnlyFn) is not awaited, which will lead to unhandled promise rejections. Additionally, an optimization is suggested for the findJobs query to conditionally execute the foundCount database query only when a state filter is active.
The getJob handler did not await rethrowAsHttp, which is wrapped in createServerOnlyFn and returns a promise. Errors thrown inside it became unhandled rejections and the handler returned undefined instead of the 404 response. Also skip the redundant found-count query in findJobs when no state filter is active, reusing the total count instead.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
findJobsandgetJobReact Query calls with TanStack Start server functions backed by a direct Drizzle/Postgres query, eliminating the round-trip through the Python REST API for job reads.jobs,job_samples,job_indexes,job_subtractions, andjob_analysestables; reconstructs the legacyargsmap from the resource junction tables at read time.build_indexjob detail view: the reference id was previously missing because it is not stored in the job args — the detail now fetches the index record and derivesref_idfrom it, restoring the broken reference and index links. Also suppresses React Query retries forUnauthorizedError/ForbiddenErrorthrown by server functions (status codes are stripped at the RPC boundary).Test plan
build_indexjob detail shows working reference and index links.JobDetail.test.tsxpasses (pnpm --filter @virtool/web exec vitest run src/jobs/components/__tests__/JobDetail.test.tsx).JobList.test.tsxpasses (pnpm --filter @virtool/web exec vitest run src/jobs/components/__tests__/JobList.test.tsx).