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/session-address-confirm.ts

88 lines
2.9 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import type { MothershipAddressCandidate } from "@/modules/address/types";
import type { QuoteRequest } from "@/modules/providers/quote-provider";
import { RpaError } from "@/modules/rpa/errors";
import { RPAContext } from "@/workers/rpa/kernel/context";
import { fillAddressStep } from "@/workers/rpa/kernel/steps/address-step";
import {
parkQuoteSession,
prepareParkedQuotePage,
takeParkedQuoteSession,
} from "@/workers/rpa/parked-quote-session";
import { captureRpaDebugScreenshot } from "@/workers/rpa/page-prep";
import { persistContext } from "@/workers/rpa/session-manager";
function candidateToAddressFields(
candidate: MothershipAddressCandidate,
): QuoteRequest["pickup"] {
return {
street: candidate.street,
city: candidate.city,
state: candidate.state,
zip: candidate.zip,
placeId: candidate.option_id,
formattedAddress: candidate.formatted_address,
selectedFromSuggestions: true,
mothershipOptionId: candidate.option_id,
mothershipDisplayLabel: candidate.display_label,
selectedFromMothership: true,
};
}
function minimalQuoteRequest(
sessionId: string,
pickup: MothershipAddressCandidate,
delivery: MothershipAddressCandidate,
): QuoteRequest {
return {
cargoHash: "session-confirm",
quoteSessionId: sessionId,
pickup: candidateToAddressFields(pickup),
delivery: candidateToAddressFields(delivery),
weightLb: 1,
dimsIn: { l: 48, w: 40, h: 48 },
palletCount: 1,
cargoType: "general_freight",
};
}
/**
* 用户确认候选后:在同驻留页点选双地址并重新 park
* 后续询价 job 可跳过 fillAddress + 跳过 openQuotePage。
*/
export async function confirmAddressesOnParkedSession(input: {
sessionId: string;
pickup: MothershipAddressCandidate;
delivery: MothershipAddressCandidate;
}): Promise<void> {
const parked = await takeParkedQuoteSession(input.sessionId, {
waitMs: 3_000,
});
if (!parked) {
throw new RpaError(
"PAGE_LOAD_TIMEOUT",
"驻留浏览器会话不可用(请重新获取地址候选,并确认 RPA Worker 已启动且未走 spawn 子进程)",
{ retryable: true },
);
}
const started = Date.now();
try {
await prepareParkedQuotePage(parked.page);
const ctx = RPAContext.fromSession(parked.page, parked.context);
await fillAddressStep(
ctx,
minimalQuoteRequest(input.sessionId, input.pickup, input.delivery),
);
await persistContext(parked.context);
await parkQuoteSession(input.sessionId, parked.page, parked.context);
console.log(
`[parked-session] 地址已确认并重新驻留 session=${input.sessionId.slice(0, 8)}${Date.now() - started}ms`,
);
} catch (error) {
await captureRpaDebugScreenshot(parked.page, "session-confirm-failure");
await parked.page.close().catch(() => undefined);
await parked.context.close().catch(() => undefined);
throw error;
}
}