fix(intake): support comma-separated status filter in GET /intake/jobs — fixes mobile polling contract mismatch

This commit is contained in:
saravanakumardb1 2026-04-06 20:48:26 -07:00
parent e5f287c7ea
commit 338e80fc33
3 changed files with 24 additions and 7 deletions

View File

@ -56,16 +56,29 @@ export async function getIntakeJob(id: string, userId: string): Promise<IntakeJo
export async function listIntakeJobs(
userId: string,
productId: string,
options?: { status?: IntakeJobStatus; since?: string; limit?: number; offset?: number },
options?: { statuses?: IntakeJobStatus[]; since?: string; limit?: number; offset?: number },
): Promise<IntakeJobDoc[]> {
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(

View File

@ -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<void> {
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,

View File

@ -86,7 +86,7 @@ export const IntakeRequestSchema = z.object({
export type IntakeRequest = z.infer<typeof IntakeRequestSchema>;
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),