From e1f766f712e0b679707e180f66f3646952de2f0f Mon Sep 17 00:00:00 2001 From: Dan Gowans Date: Thu, 19 Jan 2023 15:17:45 -0500 Subject: [PATCH] cache next and previous lots to speed up paging --- handlers/lots-get/next.js | 4 ++-- handlers/lots-get/next.ts | 4 ++-- handlers/lots-get/previous.js | 4 ++-- handlers/lots-get/previous.ts | 4 ++-- handlers/lots-get/view.js | 7 +++++- handlers/lots-get/view.ts | 8 ++++++- helpers/functions.lots.d.ts | 2 ++ helpers/functions.lots.js | 31 ++++++++++++++++++++++++ helpers/functions.lots.ts | 44 +++++++++++++++++++++++++++++++++++ package-lock.json | 24 ++++++++++++++++--- package.json | 1 + 11 files changed, 120 insertions(+), 13 deletions(-) create mode 100644 helpers/functions.lots.d.ts create mode 100644 helpers/functions.lots.js create mode 100644 helpers/functions.lots.ts diff --git a/handlers/lots-get/next.js b/handlers/lots-get/next.js index 6e486332..fdbc8364 100644 --- a/handlers/lots-get/next.js +++ b/handlers/lots-get/next.js @@ -1,7 +1,7 @@ import * as configFunctions from '../../helpers/functions.config.js'; -import { getNextLotId } from '../../helpers/lotOccupancyDB/getNextLotId.js'; +import { getNextLotId } from '../../helpers/functions.lots.js'; export async function handler(request, response) { - const lotId = request.params.lotId; + const lotId = Number.parseInt(request.params.lotId, 10); const nextLotId = await getNextLotId(lotId); if (!nextLotId) { response.redirect(configFunctions.getProperty('reverseProxy.urlPrefix') + diff --git a/handlers/lots-get/next.ts b/handlers/lots-get/next.ts index e6d2312c..163c1e45 100644 --- a/handlers/lots-get/next.ts +++ b/handlers/lots-get/next.ts @@ -2,13 +2,13 @@ import type { Request, Response } from 'express' import * as configFunctions from '../../helpers/functions.config.js' -import { getNextLotId } from '../../helpers/lotOccupancyDB/getNextLotId.js' +import { getNextLotId } from '../../helpers/functions.lots.js' export async function handler( request: Request, response: Response ): Promise { - const lotId = request.params.lotId + const lotId = Number.parseInt(request.params.lotId, 10) const nextLotId = await getNextLotId(lotId) diff --git a/handlers/lots-get/previous.js b/handlers/lots-get/previous.js index db84c53d..694a88e1 100644 --- a/handlers/lots-get/previous.js +++ b/handlers/lots-get/previous.js @@ -1,7 +1,7 @@ import * as configFunctions from '../../helpers/functions.config.js'; -import { getPreviousLotId } from '../../helpers/lotOccupancyDB/getPreviousLotId.js'; +import { getPreviousLotId } from '../../helpers/functions.lots.js'; export async function handler(request, response) { - const lotId = request.params.lotId; + const lotId = Number.parseInt(request.params.lotId, 10); const previousLotId = await getPreviousLotId(lotId); if (!previousLotId) { response.redirect(configFunctions.getProperty('reverseProxy.urlPrefix') + diff --git a/handlers/lots-get/previous.ts b/handlers/lots-get/previous.ts index 7997f903..0cb1cbdf 100644 --- a/handlers/lots-get/previous.ts +++ b/handlers/lots-get/previous.ts @@ -2,13 +2,13 @@ import type { Request, Response } from 'express' import * as configFunctions from '../../helpers/functions.config.js' -import { getPreviousLotId } from '../../helpers/lotOccupancyDB/getPreviousLotId.js' +import { getPreviousLotId } from '../../helpers/functions.lots.js' export async function handler( request: Request, response: Response ): Promise { - const lotId = request.params.lotId + const lotId = Number.parseInt(request.params.lotId, 10) const previousLotId = await getPreviousLotId(lotId) diff --git a/handlers/lots-get/view.js b/handlers/lots-get/view.js index 6df4c321..891e8c43 100644 --- a/handlers/lots-get/view.js +++ b/handlers/lots-get/view.js @@ -1,8 +1,9 @@ import * as configFunctions from '../../helpers/functions.config.js'; +import { getNextLotId, getPreviousLotId } from '../../helpers/functions.lots.js'; import { getLot } from '../../helpers/lotOccupancyDB/getLot.js'; export async function handler(request, response) { const lot = await getLot(request.params.lotId); - if (!lot) { + if (lot === undefined) { response.redirect(configFunctions.getProperty('reverseProxy.urlPrefix') + '/lots/?error=lotIdNotFound'); return; @@ -11,5 +12,9 @@ export async function handler(request, response) { headTitle: lot.lotName, lot }); + response.on('finish', () => { + void getNextLotId(lot.lotId); + void getPreviousLotId(lot.lotId); + }); } export default handler; diff --git a/handlers/lots-get/view.ts b/handlers/lots-get/view.ts index b89f7836..3bfa9859 100644 --- a/handlers/lots-get/view.ts +++ b/handlers/lots-get/view.ts @@ -1,6 +1,7 @@ import type { Request, Response } from 'express' import * as configFunctions from '../../helpers/functions.config.js' +import { getNextLotId, getPreviousLotId } from '../../helpers/functions.lots.js' import { getLot } from '../../helpers/lotOccupancyDB/getLot.js' @@ -10,7 +11,7 @@ export async function handler( ): Promise { const lot = await getLot(request.params.lotId) - if (!lot) { + if (lot === undefined) { response.redirect( configFunctions.getProperty('reverseProxy.urlPrefix') + '/lots/?error=lotIdNotFound' @@ -22,6 +23,11 @@ export async function handler( headTitle: lot.lotName, lot }) + + response.on('finish', () => { + void getNextLotId(lot.lotId) + void getPreviousLotId(lot.lotId) + }) } export default handler diff --git a/helpers/functions.lots.d.ts b/helpers/functions.lots.d.ts new file mode 100644 index 00000000..31830e3b --- /dev/null +++ b/helpers/functions.lots.d.ts @@ -0,0 +1,2 @@ +export declare function getNextLotId(lotId: number): Promise; +export declare function getPreviousLotId(lotId: number): Promise; diff --git a/helpers/functions.lots.js b/helpers/functions.lots.js new file mode 100644 index 00000000..bd6754cf --- /dev/null +++ b/helpers/functions.lots.js @@ -0,0 +1,31 @@ +import NodeCache from 'node-cache'; +import getPreviousLotIdFromDatabase from './lotOccupancyDB/getPreviousLotId.js'; +import getNextLotIdFromDatabase from './lotOccupancyDB/getNextLotId.js'; +const previousLotIdCache = new NodeCache({ + stdTTL: 2 * 60 +}); +const nextLotIdCache = new NodeCache({ + stdTTL: 2 * 60 +}); +export async function getNextLotId(lotId) { + let nextLotId = nextLotIdCache.get(lotId); + if (nextLotId === undefined) { + nextLotId = await getNextLotIdFromDatabase(lotId); + if (nextLotId !== undefined) { + previousLotIdCache.set(nextLotId, lotId); + nextLotIdCache.set(lotId, nextLotId); + } + } + return nextLotId; +} +export async function getPreviousLotId(lotId) { + let previousLotId = previousLotIdCache.get(lotId); + if (previousLotId === undefined) { + previousLotId = await getPreviousLotIdFromDatabase(lotId); + if (previousLotId !== undefined) { + previousLotIdCache.set(lotId, previousLotId); + nextLotIdCache.set(previousLotId, lotId); + } + } + return previousLotId; +} diff --git a/helpers/functions.lots.ts b/helpers/functions.lots.ts new file mode 100644 index 00000000..4002ee05 --- /dev/null +++ b/helpers/functions.lots.ts @@ -0,0 +1,44 @@ +import NodeCache from 'node-cache' + +import getPreviousLotIdFromDatabase from './lotOccupancyDB/getPreviousLotId.js' +import getNextLotIdFromDatabase from './lotOccupancyDB/getNextLotId.js' + +const previousLotIdCache = new NodeCache({ + stdTTL: 2 * 60 // two minutes +}) + +const nextLotIdCache = new NodeCache({ + stdTTL: 2 * 60 // two minutes +}) + +export async function getNextLotId(lotId: number): Promise { + let nextLotId: number | undefined = nextLotIdCache.get(lotId) + + if (nextLotId === undefined) { + nextLotId = await getNextLotIdFromDatabase(lotId) + + if (nextLotId !== undefined) { + previousLotIdCache.set(nextLotId, lotId) + nextLotIdCache.set(lotId, nextLotId) + } + } + + return nextLotId +} + +export async function getPreviousLotId( + lotId: number +): Promise { + let previousLotId: number | undefined = previousLotIdCache.get(lotId) + + if (previousLotId === undefined) { + previousLotId = await getPreviousLotIdFromDatabase(lotId) + + if (previousLotId !== undefined) { + previousLotIdCache.set(lotId, previousLotId) + nextLotIdCache.set(previousLotId, lotId) + } + } + + return previousLotId +} diff --git a/package-lock.json b/package-lock.json index 370ebb23..bfd25512 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,6 +35,7 @@ "http-errors": "^2.0.0", "ical-generator": "^3.6.1", "leaflet": "^1.9.3", + "node-cache": "^5.1.2", "papaparse": "^5.3.2", "randomcolor": "^0.6.2", "session-file-store": "^1.5.0", @@ -2915,7 +2916,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true, "engines": { "node": ">=0.8" } @@ -8741,6 +8741,17 @@ "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==", "dev": true }, + "node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, "node_modules/node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", @@ -14873,8 +14884,7 @@ "clone": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "dev": true + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==" }, "clone-buffer": { "version": "1.0.0", @@ -19340,6 +19350,14 @@ "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==", "dev": true }, + "node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "requires": { + "clone": "2.x" + } + }, "node-domexception": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz", diff --git a/package.json b/package.json index b1a77ea7..d5c9258e 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "http-errors": "^2.0.0", "ical-generator": "^3.6.1", "leaflet": "^1.9.3", + "node-cache": "^5.1.2", "papaparse": "^5.3.2", "randomcolor": "^0.6.2", "session-file-store": "^1.5.0",