manual import should move to ready directly (#109)

This commit is contained in:
Shaheer Sarfaraz 2026-02-08 15:12:54 +00:00 committed by GitHub
parent bd6834f99e
commit a24522437c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 36 additions and 7 deletions

View File

@ -216,7 +216,7 @@ export const ManualImportFlow: React.FC<ManualImportFlowProps> = ({
const payload = toPayload(draft);
const created = await api.importManualJob({ job: payload });
toast.success("Job imported", {
description: "The job is now in the discovered column.",
description: "The job was tailored and moved to the ready column.",
});
await onImported(created.id);
onClose();

View File

@ -177,7 +177,7 @@ export const OrchestratorPage: React.FC = () => {
const handleManualImported = useCallback(
async (importedJobId: string) => {
await loadJobs();
navigateWithContext("discovered", importedJobId);
navigateWithContext("ready", importedJobId);
},
[loadJobs, navigateWithContext],
);

View File

@ -63,6 +63,7 @@ describe.sequential("Manual jobs API routes", () => {
});
it("imports manual jobs and generates a fallback URL", async () => {
const { processJob } = await import("../../pipeline/index");
const { scoreJobSuitability } = await import("../../services/scorer");
vi.mocked(scoreJobSuitability).mockResolvedValue({
score: 88,
@ -84,6 +85,7 @@ describe.sequential("Manual jobs API routes", () => {
expect(body.ok).toBe(true);
expect(body.data.source).toBe("manual");
expect(body.data.jobUrl).toMatch(/^manual:\/\//);
expect(vi.mocked(processJob)).toHaveBeenCalledWith(body.data.id);
await new Promise((resolve) => setTimeout(resolve, 25));
});
});

View File

@ -8,6 +8,7 @@ import type {
import { type Request, type Response, Router } from "express";
import { JSDOM } from "jsdom";
import { z } from "zod";
import { processJob } from "../../pipeline/index";
import * as jobsRepo from "../../repositories/jobs";
import { inferManualJobDetails } from "../../services/manualJob";
import { getProfile } from "../../services/profile";
@ -234,6 +235,26 @@ manualJobsRouter.post("/import", async (req: Request, res: Response) => {
starting: cleanOptional(job.starting) ?? undefined,
});
const processResult = await processJob(createdJob.id);
if (!processResult.success) {
logger.warn("Manual job auto-processing failed", {
jobId: createdJob.id,
error: processResult.error ?? "Unknown error",
});
return res.status(502).json({
success: false,
error:
processResult.error ||
"Imported job but failed to move it to ready automatically",
details: { jobId: createdJob.id },
});
}
const processedJob = await jobsRepo.getJobById(createdJob.id);
if (!processedJob) {
return res.status(404).json({ success: false, error: "Job not found" });
}
// Score asynchronously so the import returns immediately.
(async () => {
try {
@ -247,21 +268,27 @@ manualJobsRouter.post("/import", async (req: Request, res: Response) => {
}
const profile = rawProfile as Record<string, unknown>;
const { score, reason } = await scoreJobSuitability(
createdJob,
processedJob,
profile,
);
await jobsRepo.updateJob(createdJob.id, {
await jobsRepo.updateJob(processedJob.id, {
suitabilityScore: score,
suitabilityReason: reason,
});
} catch (error) {
logger.warn("Manual job scoring failed", error);
logger.warn("Manual job scoring failed", {
jobId: processedJob.id,
error,
});
}
})().catch((error) => {
logger.warn("Manual job scoring task failed to start", error);
logger.warn("Manual job scoring task failed to start", {
jobId: processedJob.id,
error,
});
});
res.json({ success: true, data: createdJob });
res.json({ success: true, data: processedJob });
} catch (error) {
if (error instanceof z.ZodError) {
return res.status(400).json({ success: false, error: error.message });