Log export lifecycle (start/ok/fail/lock) with stack and timing

This commit is contained in:
Misaka_Company
2026-06-24 13:40:27 +08:00
parent 3371a8af2a
commit bc0e95157c

View File

@@ -1,6 +1,7 @@
import { NextResponse } from "next/server";
import sql from "mssql";
import ExcelJS from "exceljs";
import { exportLogger, formatError } from "../../../server/logger";
const dbConfig = {
server: process.env.DB_SERVER!,
@@ -55,7 +56,7 @@ const EXPORT_LOCK_TIMEOUT_MS = 90_000; // safety: reclaim a stuck lock after 90s
function acquireExportLock(): boolean {
if (exportLocked && Date.now() - exportLockedAt > EXPORT_LOCK_TIMEOUT_MS) {
console.warn("Export lock reclaimed after timeout");
exportLogger.warn("export lock reclaimed after timeout");
exportLocked = false;
}
if (exportLocked) return false;
@@ -70,11 +71,14 @@ function releaseExportLock() {
export async function GET() {
if (!acquireExportLock()) {
exportLogger.warn("export skipped: another export in progress (429)");
return NextResponse.json(
{ error: "正在导出,请稍候" },
{ status: 429, headers: { "Retry-After": "3" } }
);
}
const t0 = Date.now();
exportLogger.info("export started");
let pool: sql.ConnectionPool | undefined;
try {
pool = await sql.connect(dbConfig);
@@ -84,6 +88,7 @@ export async function GET() {
const recordset = result.recordset;
if (!recordset || recordset.length === 0) {
exportLogger.warn("export empty: no data");
return NextResponse.json({ error: "没有数据可导出" }, { status: 404 });
}
@@ -151,6 +156,12 @@ export async function GET() {
// Stream to buffer
const buffer = await workbook.xlsx.writeBuffer();
const bytes =
typeof buffer === "object" && buffer && "byteLength" in buffer
? (buffer as { byteLength: number }).byteLength
: 0;
const dur = Date.now() - t0;
exportLogger.info(`export ok · rows=${recordset.length} · bytes=${bytes} · dur=${dur}ms`);
return new NextResponse(buffer, {
status: 200,
@@ -162,8 +173,9 @@ export async function GET() {
},
});
} catch (err) {
const dur = Date.now() - t0;
const message = err instanceof Error ? err.message : "Unknown error";
console.error("Excel export error:", message);
exportLogger.error(`export failed · dur=${dur}ms · ${formatError(err)}`);
return NextResponse.json({ error: message }, { status: 500 });
} finally {
if (pool) {