feat: add BullMQ queue infrastructure and frontend job status hook
- apps/Backend/src/queue/: connection, queues, workers, processors - apps/Frontend/src/hooks/use-job-status.ts: WebSocket job progress hook - apps/Frontend/src/lib/socket.ts: shared Socket.IO singleton Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
99
apps/Backend/src/queue/processors/claimStatusProcessor.ts
Normal file
99
apps/Backend/src/queue/processors/claimStatusProcessor.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* Processor for "claim-status-check" jobs.
|
||||
* Mirrors routes/insuranceStatus.ts /claim-status-check
|
||||
*/
|
||||
import fs from "fs/promises";
|
||||
import fsSync from "fs";
|
||||
import path from "path";
|
||||
import { storage } from "../../storage";
|
||||
import { emptyFolderContainingFile } from "../../utils/emptyTempFolder";
|
||||
import {
|
||||
startPythonJob,
|
||||
pollPythonJob,
|
||||
imageToPdfBuffer,
|
||||
} from "./_shared";
|
||||
|
||||
export interface ClaimStatusProcessorInput {
|
||||
enrichedPayload: any;
|
||||
insuranceId: string; // memberId used to look up the patient
|
||||
}
|
||||
|
||||
export interface ClaimStatusProcessorResult {
|
||||
pdfUploadStatus?: string;
|
||||
pdfFileId?: number | null;
|
||||
}
|
||||
|
||||
export async function runClaimStatusProcessor(
|
||||
input: ClaimStatusProcessorInput
|
||||
): Promise<ClaimStatusProcessorResult> {
|
||||
const { enrichedPayload, insuranceId } = input;
|
||||
|
||||
// 1) Start async Python job
|
||||
const sid = await startPythonJob("/claim-status-check/async", {
|
||||
data: enrichedPayload,
|
||||
});
|
||||
|
||||
// 2) Poll for completion
|
||||
const result = await pollPythonJob(sid);
|
||||
|
||||
const outputResult: ClaimStatusProcessorResult = {};
|
||||
|
||||
// 3) Look up patient
|
||||
const patient = await storage.getPatientByInsuranceId(insuranceId);
|
||||
|
||||
if (patient && patient.id !== undefined) {
|
||||
let pdfBuffer: Buffer | null = null;
|
||||
let generatedPdfPath: string | null = null;
|
||||
|
||||
if (
|
||||
result.ss_path &&
|
||||
/\.(png|jpg|jpeg)$/i.test(result.ss_path) &&
|
||||
fsSync.existsSync(result.ss_path)
|
||||
) {
|
||||
try {
|
||||
pdfBuffer = await imageToPdfBuffer(result.ss_path);
|
||||
const pdfFileName = `claimStatus_${insuranceId}_${Date.now()}.pdf`;
|
||||
generatedPdfPath = path.join(path.dirname(result.ss_path), pdfFileName);
|
||||
await fs.writeFile(generatedPdfPath, pdfBuffer);
|
||||
} catch (e) {
|
||||
console.error("[claimStatusProcessor] img→PDF conversion failed:", e);
|
||||
outputResult.pdfUploadStatus = `Failed to convert screenshot to PDF: ${e}`;
|
||||
}
|
||||
} else {
|
||||
outputResult.pdfUploadStatus =
|
||||
"No valid screenshot provided by Selenium; nothing to upload.";
|
||||
}
|
||||
|
||||
if (pdfBuffer && generatedPdfPath) {
|
||||
const groupTitleKey = "CLAIM_STATUS";
|
||||
const groupTitle = "Claim Status";
|
||||
|
||||
let group = await storage.findPdfGroupByPatientTitleKey(patient.id, groupTitleKey);
|
||||
if (!group) group = await storage.createPdfGroup(patient.id, groupTitle, groupTitleKey);
|
||||
if (!group?.id) throw new Error("PDF group creation failed");
|
||||
|
||||
const basename = path.basename(generatedPdfPath);
|
||||
const created = await storage.createPdfFile(group.id, basename, pdfBuffer);
|
||||
|
||||
let createdPdfFileId: number | null = null;
|
||||
if (created && typeof created === "object" && "id" in created) {
|
||||
createdPdfFileId = Number(created.id);
|
||||
}
|
||||
|
||||
outputResult.pdfUploadStatus = `PDF saved to group: ${group.title}`;
|
||||
outputResult.pdfFileId = createdPdfFileId;
|
||||
}
|
||||
} else {
|
||||
outputResult.pdfUploadStatus =
|
||||
"Patient not found; no PDF saved.";
|
||||
}
|
||||
|
||||
// 4) Cleanup
|
||||
try {
|
||||
if (result.ss_path) await emptyFolderContainingFile(result.ss_path);
|
||||
} catch (e) {
|
||||
console.error("[claimStatusProcessor] cleanup failed:", e);
|
||||
}
|
||||
|
||||
return outputResult;
|
||||
}
|
||||
Reference in New Issue
Block a user