diff --git a/backend/src/modules/intake/repository.ts b/backend/src/modules/intake/repository.ts index 9e6a345..8ce1232 100644 --- a/backend/src/modules/intake/repository.ts +++ b/backend/src/modules/intake/repository.ts @@ -56,16 +56,29 @@ export async function getIntakeJob(id: string, userId: string): Promise { const filter: FilterMap = { userId, productId }; - if (options?.status) filter.status = options.status; - return jobsCollection().findMany({ + // If a single status is provided, use it as a direct filter for efficiency + if (options?.statuses && options.statuses.length === 1) { + filter.status = options.statuses[0]; + } + const limit = options?.limit ?? 20; + // Fetch more if we need to filter client-side for multiple statuses + const fetchLimit = options?.statuses && options.statuses.length > 1 ? Math.min(limit * 3, 100) : limit; + let jobs = await jobsCollection().findMany({ filter, sort: { startedAt: -1 }, - limit: options?.limit ?? 20, + limit: fetchLimit, offset: options?.offset ?? 0, }); + // Client-side filter for multiple statuses + if (options?.statuses && options.statuses.length > 1) { + const statusSet = new Set(options.statuses); + jobs = jobs.filter((j) => statusSet.has(j.status)); + jobs = jobs.slice(0, limit); + } + return jobs; } export async function updateIntakeJob( diff --git a/backend/src/modules/intake/routes.ts b/backend/src/modules/intake/routes.ts index 6f5e0e3..6f49181 100644 --- a/backend/src/modules/intake/routes.ts +++ b/backend/src/modules/intake/routes.ts @@ -23,7 +23,7 @@ import { UpdateIntakeRuleSchema, ListIntakeJobsQuerySchema, } from './types.js'; -import type { IntakeRuleDoc } from './types.js'; +import type { IntakeRuleDoc, IntakeJobStatus } from './types.js'; // ── Rate limiter (simple in-memory) ────────────────────────────── @@ -249,8 +249,12 @@ export async function intakeRoutes(app: FastifyInstance): Promise { const userId = getUserId(req); const productId = getRequestProductId(req); const query = ListIntakeJobsQuerySchema.parse(req.query); + // Support comma-separated statuses (e.g. "queued,extracting,processing") + const statuses = query.status + ? query.status.split(',').map((s) => s.trim()).filter(Boolean) as IntakeJobStatus[] + : undefined; const jobs = await repo.listIntakeJobs(userId, productId, { - status: query.status, + statuses, since: query.since, limit: query.limit, offset: query.offset, diff --git a/backend/src/modules/intake/types.ts b/backend/src/modules/intake/types.ts index 1570ec5..2393019 100644 --- a/backend/src/modules/intake/types.ts +++ b/backend/src/modules/intake/types.ts @@ -86,7 +86,7 @@ export const IntakeRequestSchema = z.object({ export type IntakeRequest = z.infer; export const ListIntakeJobsQuerySchema = z.object({ - status: z.enum(INTAKE_JOB_STATUSES).optional(), + status: z.string().max(200).optional(), since: z.string().max(64).optional(), limit: z.coerce.number().int().min(1).max(100).default(20), offset: z.coerce.number().int().min(0).default(0),