Log export lifecycle (start/ok/fail/lock) with stack and timing
This commit is contained in:
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user