build: compile dist for sitemap, favicon, and graceful shutdown changes
All checks were successful
Deploy to Production / Deploy to Server (push) Successful in 1m12s
All checks were successful
Deploy to Production / Deploy to Server (push) Successful in 1m12s
This commit is contained in:
parent
d7b0a0eaa6
commit
5b7e343139
2 changed files with 47 additions and 7 deletions
52
dist/index.js
vendored
52
dist/index.js
vendored
|
|
@ -20,7 +20,7 @@ import { pdfRateLimitMiddleware, getConcurrencyStats } from "./middleware/pdfRat
|
|||
import { initBrowser, closeBrowser } from "./services/browser.js";
|
||||
import { loadKeys, getAllKeys } from "./services/keys.js";
|
||||
import { verifyToken, loadVerifications } from "./services/verification.js";
|
||||
import { initDatabase } from "./services/db.js";
|
||||
import { initDatabase, pool } from "./services/db.js";
|
||||
const app = express();
|
||||
const PORT = parseInt(process.env.PORT || "3100", 10);
|
||||
app.use(helmet({ crossOriginResourcePolicy: { policy: "cross-origin" } }));
|
||||
|
|
@ -152,6 +152,12 @@ ${apiKey ? `
|
|||
}
|
||||
// Landing page
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
// Favicon route
|
||||
app.get("/favicon.ico", (_req, res) => {
|
||||
res.setHeader('Content-Type', 'image/svg+xml');
|
||||
res.setHeader('Cache-Control', 'public, max-age=604800');
|
||||
res.sendFile(path.join(__dirname, "../public/favicon.svg"));
|
||||
});
|
||||
app.use(express.static(path.join(__dirname, "../public"), {
|
||||
maxAge: "1d",
|
||||
etag: true,
|
||||
|
|
@ -270,14 +276,46 @@ async function start() {
|
|||
await loadUsageData();
|
||||
await initBrowser();
|
||||
logger.info(`Loaded ${getAllKeys().length} API keys`);
|
||||
app.listen(PORT, () => logger.info(`DocFast API running on :${PORT}`));
|
||||
const shutdown = async () => {
|
||||
logger.info("Shutting down...");
|
||||
await closeBrowser();
|
||||
const server = app.listen(PORT, () => logger.info(`DocFast API running on :${PORT}`));
|
||||
let shuttingDown = false;
|
||||
const shutdown = async (signal) => {
|
||||
if (shuttingDown)
|
||||
return;
|
||||
shuttingDown = true;
|
||||
logger.info(`Received ${signal}, starting graceful shutdown...`);
|
||||
// 1. Stop accepting new connections, wait for in-flight requests (max 10s)
|
||||
await new Promise((resolve) => {
|
||||
const forceTimeout = setTimeout(() => {
|
||||
logger.warn("Forcing server close after 10s timeout");
|
||||
resolve();
|
||||
}, 10_000);
|
||||
server.close(() => {
|
||||
clearTimeout(forceTimeout);
|
||||
logger.info("HTTP server closed (all in-flight requests completed)");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
// 2. Close Puppeteer browser pool
|
||||
try {
|
||||
await closeBrowser();
|
||||
logger.info("Browser pool closed");
|
||||
}
|
||||
catch (err) {
|
||||
logger.error({ err }, "Error closing browser pool");
|
||||
}
|
||||
// 3. Close PostgreSQL connection pool
|
||||
try {
|
||||
await pool.end();
|
||||
logger.info("PostgreSQL pool closed");
|
||||
}
|
||||
catch (err) {
|
||||
logger.error({ err }, "Error closing PostgreSQL pool");
|
||||
}
|
||||
logger.info("Graceful shutdown complete");
|
||||
process.exit(0);
|
||||
};
|
||||
process.on("SIGTERM", shutdown);
|
||||
process.on("SIGINT", shutdown);
|
||||
process.on("SIGTERM", () => shutdown("SIGTERM"));
|
||||
process.on("SIGINT", () => shutdown("SIGINT"));
|
||||
}
|
||||
start().catch((err) => {
|
||||
logger.error({ err }, "Failed to start");
|
||||
|
|
|
|||
2
dist/services/browser.js
vendored
2
dist/services/browser.js
vendored
|
|
@ -196,6 +196,7 @@ export async function closeBrowser() {
|
|||
export async function renderPdf(html, options = {}) {
|
||||
const { page, instance } = await acquirePage();
|
||||
try {
|
||||
await page.setJavaScriptEnabled(false);
|
||||
const result = await Promise.race([
|
||||
(async () => {
|
||||
await page.setContent(html, { waitUntil: "domcontentloaded", timeout: 15_000 });
|
||||
|
|
@ -222,6 +223,7 @@ export async function renderPdf(html, options = {}) {
|
|||
export async function renderUrlPdf(url, options = {}) {
|
||||
const { page, instance } = await acquirePage();
|
||||
try {
|
||||
await page.setJavaScriptEnabled(false);
|
||||
const result = await Promise.race([
|
||||
(async () => {
|
||||
await page.goto(url, {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue