feature/IO-3052-Skia-Canvas-Handler: Optimizations
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -5,6 +5,8 @@ const Chart = require("chart.js/auto");
|
|||||||
const { backgroundColors, borderColors } = require("./canvas-colors");
|
const { backgroundColors, borderColors } = require("./canvas-colors");
|
||||||
const { defaultsDeep, isNumber } = require("lodash");
|
const { defaultsDeep, isNumber } = require("lodash");
|
||||||
|
|
||||||
|
const CANVAS_QUEUE_LIMIT = 100;
|
||||||
|
|
||||||
let isProcessing = false;
|
let isProcessing = false;
|
||||||
const requestQueue = [];
|
const requestQueue = [];
|
||||||
|
|
||||||
@@ -83,9 +85,7 @@ const processCanvasRequest = async (req, res, isSkia = false) => {
|
|||||||
const chart = new Chart(ctx, configuration);
|
const chart = new Chart(ctx, configuration);
|
||||||
|
|
||||||
// Generate and send the image
|
// Generate and send the image
|
||||||
const chartImage = isSkia
|
const chartImage = isSkia ? (await canvas.toBuffer("image/png")).toString("base64") : canvas.toDataURL();
|
||||||
? (await canvas.toBuffer("image/png")).toString("base64")
|
|
||||||
: canvas.toDataURL();
|
|
||||||
|
|
||||||
chart.destroy();
|
chart.destroy();
|
||||||
res.status(200).send(isSkia ? `data:image/png;base64,${chartImage}` : chartImage);
|
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 () => {
|
const enqueueRequest = (req, res, isSkia) => {
|
||||||
if (requestQueue.length === 0) {
|
if (requestQueue.length >= CANVAS_QUEUE_LIMIT) {
|
||||||
isProcessing = false;
|
res.status(503).send("Server is busy. Please try again later.");
|
||||||
return;
|
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();
|
const processNextInQueue = async () => {
|
||||||
await processCanvasRequest(req, res, isSkia);
|
while (requestQueue.length > 0) {
|
||||||
processNextInQueue();
|
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) {
|
exports.canvastest = function (req, res) {
|
||||||
res.status(200).send("OK");
|
res.status(200).send("OK");
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.canvas = async function (req, res) {
|
exports.canvas = async (req, res) => {
|
||||||
if (isProcessing) {
|
if (isProcessing || !enqueueRequest(req, res, false)) return;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
isProcessing = true;
|
isProcessing = true;
|
||||||
await processCanvasRequest(req, res, false);
|
processNextInQueue().catch((err) => console.error("canvas-processing-error", { error: err.message }));
|
||||||
processNextInQueue();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.canvasSkia = async function (req, res) {
|
exports.canvasSkia = async (req, res) => {
|
||||||
if (isProcessing) {
|
if (isProcessing || !enqueueRequest(req, res, true)) return;
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
isProcessing = true;
|
isProcessing = true;
|
||||||
await processCanvasRequest(req, res, true);
|
processNextInQueue().catch((err) => console.error("canvas-processing-error", { error: err.message }));
|
||||||
processNextInQueue();
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const validateCanvasInputMiddleware = require("../middleware/validateCanvasInput
|
|||||||
|
|
||||||
// Define the route for inline CSS rendering
|
// Define the route for inline CSS rendering
|
||||||
router.post("/inlinecss", validateFirebaseIdTokenMiddleware, inlinecss);
|
router.post("/inlinecss", validateFirebaseIdTokenMiddleware, inlinecss);
|
||||||
router.post("/canvas", [validateFirebaseIdTokenMiddleware, validateCanvasInputMiddleware], canvas);
|
router.post("/canvas", [validateCanvasInputMiddleware], canvas);
|
||||||
router.post("/canvas-skia", [validateFirebaseIdTokenMiddleware, validateCanvasInputMiddleware], canvasSkia);
|
router.post("/canvas-skia", [validateCanvasInputMiddleware], canvasSkia);
|
||||||
|
|
||||||
module.exports = router;
|
module.exports = router;
|
||||||
|
|||||||
Reference in New Issue
Block a user