From c507f708eb9196bc7ee564e481d317b44c05d96b Mon Sep 17 00:00:00 2001 From: Tom Butcher Date: Sun, 21 Jun 2026 15:42:19 +0100 Subject: [PATCH] Enhanced app update service with Redis caching for branch retrieval and current build information, improving performance and reducing API calls. --- src/services/misc/appupdate.js | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/src/services/misc/appupdate.js b/src/services/misc/appupdate.js index ca2608d..f9a8647 100644 --- a/src/services/misc/appupdate.js +++ b/src/services/misc/appupdate.js @@ -1,10 +1,16 @@ import axios from 'axios'; import config from '../../config.js'; import log4js from 'log4js'; +import { redisServer } from '../../database/redis.js'; const logger = log4js.getLogger('AppUpdate'); logger.level = config.server.logLevel; +const APP_UPDATE_PREFIX = 'appupdate:'; +const APP_UPDATE_BRANCHES_KEY = `${APP_UPDATE_PREFIX}branches`; +const APP_UPDATE_CURRENT_PREFIX = `${APP_UPDATE_PREFIX}current:`; +const APP_UPDATE_TTL_SECONDS = 120; + const normalizeProjectUrl = (projectUrl) => { if (typeof projectUrl !== 'string') return ''; return projectUrl.replace(/\/+$/, ''); @@ -33,6 +39,11 @@ const mapArtifacts = (build, requestedBranch) => { }; const getBranchesFromJenkins = async () => { + const cached = await redisServer.getKey(APP_UPDATE_BRANCHES_KEY); + if (cached) { + return cached; + } + const projectUrl = getProjectUrl(); if (!projectUrl) { throw new Error('Missing config.app.jenkinsProject'); @@ -42,13 +53,16 @@ const getBranchesFromJenkins = async () => { const response = await axios.get(jenkinsUrl, { timeout: 10000 }); const jobs = Array.isArray(response.data?.jobs) ? response.data.jobs : []; - return jobs + const branches = jobs .map((job) => ({ name: job.name, url: job.url, color: job.color, })) .filter((job) => typeof job.name === 'string' && typeof job.url === 'string'); + + await redisServer.setKey(APP_UPDATE_BRANCHES_KEY, branches, APP_UPDATE_TTL_SECONDS); + return branches; }; const getLatestBuildForBranch = async (branchUrl) => { @@ -91,7 +105,14 @@ export const appUpdateCurrentRouteHandler = async (req, res) => { return res.status(400).send({ error: 'branch query parameter is required' }); } + const currentCacheKey = `${APP_UPDATE_CURRENT_PREFIX}${requestedBranch}`; + try { + const cachedCurrent = await redisServer.getKey(currentCacheKey); + if (cachedCurrent) { + return res.send(cachedCurrent); + } + const branches = await getBranchesFromJenkins(); const branch = branches.find((item) => item.name === requestedBranch); @@ -111,7 +132,7 @@ export const appUpdateCurrentRouteHandler = async (req, res) => { logger.error('Failed to parse version from build display name:', error); } - return res.send({ + const payload = { branch: requestedBranch, buildNumber: build.number, version: version, @@ -121,7 +142,10 @@ export const appUpdateCurrentRouteHandler = async (req, res) => { builtAt: new Date(build.timestamp).toISOString(), buildSource: source, artifacts: mapArtifacts(build, requestedBranch), - }); + }; + + await redisServer.setKey(currentCacheKey, payload, APP_UPDATE_TTL_SECONDS); + return res.send(payload); } catch (error) { logger.error('Failed to fetch Jenkins build info:', error); return res.status(500).send({