diff --git a/server/render/canvas-handler.js b/server/render/canvas-handler.js index 946b6d082..0da0cc9a2 100644 --- a/server/render/canvas-handler.js +++ b/server/render/canvas-handler.js @@ -5,6 +5,8 @@ const Chart = require("chart.js/auto"); const { backgroundColors, borderColors } = require("./canvas-colors"); const { defaultsDeep, isNumber } = require("lodash"); +const CANVAS_QUEUE_LIMIT = 100; + let isProcessing = false; const requestQueue = []; @@ -83,9 +85,7 @@ const processCanvasRequest = async (req, res, isSkia = false) => { const chart = new Chart(ctx, configuration); // Generate and send the image - const chartImage = isSkia - ? (await canvas.toBuffer("image/png")).toString("base64") - : canvas.toDataURL(); + const chartImage = isSkia ? (await canvas.toBuffer("image/png")).toString("base64") : canvas.toDataURL(); chart.destroy(); res.status(200).send(isSkia ? `data:image/png;base64,${chartImage}` : chartImage); @@ -95,49 +95,40 @@ const processCanvasRequest = async (req, res, isSkia = false) => { } }; -const processNextInQueue = async () => { - if (requestQueue.length === 0) { - isProcessing = false; - return; +const enqueueRequest = (req, res, isSkia) => { + if (requestQueue.length >= CANVAS_QUEUE_LIMIT) { + res.status(503).send("Server is busy. Please try again later."); + return false; } + requestQueue.push({ req, res, isSkia }); + req.logger.log("inbound-canvas-creation-queue", "debug", "jsr", null, { queue: requestQueue.length }); + return true; +}; - const { req, res, isSkia } = requestQueue.shift(); - await processCanvasRequest(req, res, isSkia); - processNextInQueue(); +const processNextInQueue = async () => { + while (requestQueue.length > 0) { + const { req, res, isSkia } = requestQueue.shift(); + try { + await processCanvasRequest(req, res, isSkia); + } catch (err) { + console.error("canvas-queue-error", "error", "jsr", null, { error: err.message }); + } + } + isProcessing = false; }; exports.canvastest = function (req, res) { res.status(200).send("OK"); }; -exports.canvas = async function (req, res) { - if (isProcessing) { - if (requestQueue.length >= 100) { - // Set a maximum queue size - return res.status(503).send("Server is busy. Please try again later."); - } - requestQueue.push({ req, res, isSkia: false }); - req.logger.log("inbound-canvas-creation-queue", "debug", "jsr", null, { queue: requestQueue.length }); - return; - } - +exports.canvas = async (req, res) => { + if (isProcessing || !enqueueRequest(req, res, false)) return; isProcessing = true; - await processCanvasRequest(req, res, false); - processNextInQueue(); + processNextInQueue().catch((err) => console.error("canvas-processing-error", { error: err.message })); }; -exports.canvasSkia = async function (req, res) { - if (isProcessing) { - if (requestQueue.length >= 100) { - // Set a maximum queue size - return res.status(503).send("Server is busy. Please try again later."); - } - requestQueue.push({ req, res, isSkia: true }); - req.logger.log("inbound-canvas-creation-queue", "debug", "jsr", null, { queue: requestQueue.length }); - return; - } - +exports.canvasSkia = async (req, res) => { + if (isProcessing || !enqueueRequest(req, res, true)) return; isProcessing = true; - await processCanvasRequest(req, res, true); - processNextInQueue(); + processNextInQueue().catch((err) => console.error("canvas-processing-error", { error: err.message })); }; diff --git a/server/routes/renderRoutes.js b/server/routes/renderRoutes.js index c1423f698..fda1b5846 100644 --- a/server/routes/renderRoutes.js +++ b/server/routes/renderRoutes.js @@ -7,7 +7,7 @@ const validateCanvasInputMiddleware = require("../middleware/validateCanvasInput // Define the route for inline CSS rendering router.post("/inlinecss", validateFirebaseIdTokenMiddleware, inlinecss); -router.post("/canvas", [validateFirebaseIdTokenMiddleware, validateCanvasInputMiddleware], canvas); -router.post("/canvas-skia", [validateFirebaseIdTokenMiddleware, validateCanvasInputMiddleware], canvasSkia); +router.post("/canvas", [validateCanvasInputMiddleware], canvas); +router.post("/canvas-skia", [validateCanvasInputMiddleware], canvasSkia); module.exports = router;