You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
chajia/workers/rpa/ms-refine-job-handler.ts

129 lines
4.6 KiB

/**
* MotherShip 登录态二级刷价 job
*/
import type { MsRefineDetailsJobData } from "@/modules/mothership/refine-queue";
import { cargoToQuoteRequest } from "@/modules/rpa/quote-mapper";
import { RpaError } from "@/modules/rpa/errors";
import { clearMsRefineHold } from "@/lib/mothership/refine-hold-store";
import { getCustomerProviderLogin } from "@/modules/customer/provider-credentials";
import { runWithMothershipLoginContext } from "@/lib/rpa/mothership-login-context";
import { runMothershipLoggedInRefineOnParked } from "@/workers/rpa/mothership-logged-in-quote";
import { releaseParkedQuoteSession } from "@/workers/rpa/parked-quote-session";
import { requestReleaseParkedSession } from "@/modules/address/parked-session-queue";
import { applyMsRefineQuotes } from "@/modules/mothership/refine-apply-quotes";
import {
fetchMothershipLoggedInDirectQuote,
isMsDashboardDirectQuoteEnabled,
} from "@/lib/mothership/dashboard-direct-quote";
import type { QuoteItem } from "@/modules/providers/quote-provider";
import { prisma } from "@/lib/prisma";
export async function processMsRefineDetailsJob(
data: MsRefineDetailsJobData,
): Promise<void> {
const customerLogin = await getCustomerProviderLogin(
data.customerId,
"mothership",
);
const email =
customerLogin?.email?.trim() || process.env.MOTHERSHIP_EMAIL?.trim() || "";
const password =
customerLogin?.password?.trim() ||
process.env.MOTHERSHIP_PASSWORD?.trim() ||
"";
try {
const req = cargoToQuoteRequest(data.cargo);
req.quoteSessionId = data.sessionId;
let items: QuoteItem[] | null = null;
if (isMsDashboardDirectQuoteEnabled() && email) {
try {
items = await runWithMothershipLoginContext(
{ email, password: password || "x" },
customerLogin ? "customer" : "env",
() =>
fetchMothershipLoggedInDirectQuote(req, { allowBootstrap: false }),
);
console.log(
`[ms-refine] Direct OK quote_id=${data.quoteId} tiers=${items.length}`,
);
} catch (directErr) {
const brief =
directErr instanceof Error ? directErr.message : String(directErr);
console.warn(
`[ms-refine] Direct 失败,回退驻留 DOM quote_id=${data.quoteId} reason=${brief.slice(0, 180)}`,
);
}
}
if (!items || items.length < 1) {
items = await runWithMothershipLoginContext(
{ email, password: password || "x" },
customerLogin ? "customer" : "env",
() => runMothershipLoggedInRefineOnParked(data.sessionId, req),
);
}
await applyMsRefineQuotes({
quoteId: data.quoteId,
requestId: data.requestId,
customerId: data.customerId,
sessionId: data.sessionId,
cargo: data.cargo,
items,
});
} catch (err) {
const msg = err instanceof Error ? err.message : String(err);
const code = err instanceof RpaError ? err.code : "RPA_DATA_INVALID";
console.error(`[ms-refine] FAIL quote_id=${data.quoteId} ${msg}`);
const shouldFullRequote =
code === "SESSION_EXPIRED" ||
code === "PAGE_LOAD_TIMEOUT" ||
/会话已失效|驻留页已失效|报价会话已失效/i.test(msg);
await releaseParkedQuoteSession(data.sessionId).catch(() => undefined);
await requestReleaseParkedSession(data.sessionId).catch(() => undefined);
await clearMsRefineHold(data.sessionId).catch(() => undefined);
if (shouldFullRequote) {
// 驻留失效:用原地址 + 补充信息完整重查,不向客户暴露超时
const { enqueueQuoteJob } = await import("@/modules/quote/rpa-queue");
await prisma.quoteRecord
.update({
where: { quoteId: data.quoteId },
data: { status: "processing", errorCode: null, errorMessage: null },
})
.catch(() => undefined);
const cargo = { ...data.cargo };
delete (cargo as { quoteSessionId?: string }).quoteSessionId;
await enqueueQuoteJob({
quoteId: data.quoteId,
requestId: data.requestId,
customerId: data.customerId,
businessCustomerId: data.cargo.businessCustomerId,
cargoHash: data.cargo.cargoHash,
cargo,
});
console.warn(
`[ms-refine] 驻留失效,已降级完整重查 quote_id=${data.quoteId}`,
);
return;
}
await prisma.quoteRecord
.update({
where: { quoteId: data.quoteId },
data: {
status: "done",
errorCode: null,
},
})
.catch(() => undefined);
console.warn(
`[ms-refine] 刷价失败已降级保留首价 code=${code} msg=${msg.slice(0, 200)}`,
);
}
}