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.

69 lines
1.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 { getHostQuotePollIntervalMs } from "@/lib/constants/host-public-api";
import { QUOTE_TIMEOUT_MS } from "@/lib/constants/quote";
import { prisma } from "@/lib/prisma";
import {
serializeQuoteDetail,
type QuoteDetailResponse,
} from "@/modules/quote/quote-serializer";
function sleep(ms: number): Promise<void> {
return new Promise((resolve) => setTimeout(resolve, ms));
}
export class HostQuoteWaitError extends Error {
constructor(
message: string,
readonly code: "QUOTE_NOT_FOUND" | "QUOTE_TIMEOUT" | "QUOTE_FAILED",
readonly detail?: QuoteDetailResponse,
) {
super(message);
this.name = "HostQuoteWaitError";
}
}
/** 服务端轮询 DB直至报价完成或超时供宿主同步接口使用 */
export async function waitForQuoteDetail(
quoteId: string,
customerId: string,
options?: { timeoutMs?: number },
): Promise<QuoteDetailResponse> {
const timeoutMs = options?.timeoutMs ?? QUOTE_TIMEOUT_MS;
const deadline = Date.now() + timeoutMs;
while (Date.now() < deadline) {
const record = await prisma.quoteRecord.findFirst({
where: { quoteId, customerId, isDeleted: false },
});
if (!record) {
throw new HostQuoteWaitError("报价不存在", "QUOTE_NOT_FOUND");
}
const detail = serializeQuoteDetail(record);
if (detail.status === "processing") {
const remaining = deadline - Date.now();
if (remaining <= 0) {
break;
}
await sleep(Math.min(getHostQuotePollIntervalMs(), remaining));
continue;
}
if (detail.status === "failed") {
throw new HostQuoteWaitError(
detail.error_message ?? "询价失败",
"QUOTE_FAILED",
detail,
);
}
if (detail.status === "expired") {
throw new HostQuoteWaitError("报价已过期", "QUOTE_FAILED", detail);
}
return detail;
}
throw new HostQuoteWaitError("询价超时,请稍后重试", "QUOTE_TIMEOUT");
}