From 107521e45a3f101e09c86a683cb6aca2514ae477 Mon Sep 17 00:00:00 2001 From: Daniel Salazar Date: Sun, 29 Mar 2026 13:07:00 -0700 Subject: [PATCH] fix: remove recommended app caching in favour of stronger caching at app fetch layer (#2748) --- src/backend/src/clients/redis/cacheUpdate.ts | 2 +- src/backend/src/helpers.js | 4 +- .../src/modules/apps/AppRedisCacheSpace.js | 2 +- .../apps/RecommendedAppsRedisCacheSpace.js | 21 -------- .../modules/apps/RecommendedAppsService.js | 52 ++----------------- 5 files changed, 8 insertions(+), 73 deletions(-) delete mode 100644 src/backend/src/modules/apps/RecommendedAppsRedisCacheSpace.js diff --git a/src/backend/src/clients/redis/cacheUpdate.ts b/src/backend/src/clients/redis/cacheUpdate.ts index 8d354a5c2..4136cacb8 100644 --- a/src/backend/src/clients/redis/cacheUpdate.ts +++ b/src/backend/src/clients/redis/cacheUpdate.ts @@ -118,6 +118,6 @@ export const setRedisCacheValue = async ( if ( ttlSeconds ) { await redisClient.set(key, value, 'EX', ttlSeconds); } else { - await redisClient.set(key, value); + await redisClient.set(key, value, 'EX', 60 * 10); // default to 10 min if no ttl provided } }; diff --git a/src/backend/src/helpers.js b/src/backend/src/helpers.js index e0a4cb4c8..a4bceddee 100644 --- a/src/backend/src/helpers.js +++ b/src/backend/src/helpers.js @@ -364,7 +364,7 @@ export async function get_app (options) { const cacheApp = async (app) => { if ( ! app ) return; AppRedisCacheSpace.setCachedApp(app, { - ttlSeconds: 30, + ttlSeconds: 300, }); }; const isDecoratedAppCacheEntry = (app) => ( @@ -550,7 +550,7 @@ export const get_apps = spanify('get_apps', async (specifiers, options = {}) => const cacheApp = async (app) => { if ( ! app ) return; AppRedisCacheSpace.setCachedApp(app, { - ttlSeconds: 60, + ttlSeconds: 300, }); }; diff --git a/src/backend/src/modules/apps/AppRedisCacheSpace.js b/src/backend/src/modules/apps/AppRedisCacheSpace.js index 7c8c5c0dd..c948d4f9c 100644 --- a/src/backend/src/modules/apps/AppRedisCacheSpace.js +++ b/src/backend/src/modules/apps/AppRedisCacheSpace.js @@ -81,7 +81,7 @@ export const AppRedisCacheSpace = { if ( ! app ) return; const serialized = JSON.stringify(app); const writes = AppRedisCacheSpace.keysForApp(app) - .map(key => setKey(key, serialized, { ttlSeconds })); + .map(key => setKey(key, serialized, { ttlSeconds: ttlSeconds || 60 })); if ( writes.length ) { await Promise.all(writes); } diff --git a/src/backend/src/modules/apps/RecommendedAppsRedisCacheSpace.js b/src/backend/src/modules/apps/RecommendedAppsRedisCacheSpace.js deleted file mode 100644 index 733ccbc40..000000000 --- a/src/backend/src/modules/apps/RecommendedAppsRedisCacheSpace.js +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (C) 2024-present Puter Technologies Inc. - * - * This file is part of Puter. - * - * Puter is free software: you can redistribute it and/or modify - * it under the terms of the GNU Affero General Public License as published - * by the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Affero General Public License for more details. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -export const RecommendedAppsRedisCacheSpace = { - key: ({ iconSize } = {}) => `global:recommended-apps${iconSize ? `:icon-size:${iconSize}` : ''}`, -}; diff --git a/src/backend/src/modules/apps/RecommendedAppsService.js b/src/backend/src/modules/apps/RecommendedAppsService.js index 5936a92b4..484de7fa3 100644 --- a/src/backend/src/modules/apps/RecommendedAppsService.js +++ b/src/backend/src/modules/apps/RecommendedAppsService.js @@ -17,15 +17,11 @@ * along with this program. If not, see . */ -import { redisClient } from '../../clients/redis/redisSingleton.js'; -import { deleteRedisKeys } from '../../clients/redis/deleteRedisKeys.js'; -import { setRedisCacheValue } from '../../clients/redis/cacheUpdate.js'; import { get_apps } from '../../helpers.js'; -import BaseService from '../../services/BaseService.js'; -import { RecommendedAppsRedisCacheSpace } from './RecommendedAppsRedisCacheSpace.js'; +import { BaseService } from '../../services/BaseService.js'; export default class RecommendedAppsService extends BaseService { - static APP_NAMES = [ + appNames = new Set([ 'app-center', 'dev-center', 'editor', @@ -44,49 +40,13 @@ export default class RecommendedAppsService extends BaseService { 'galaxy-troops', 'blend-fruits', 'traffic-tap-puzzle', - ]; - - _construct () { - this.app_names = new Set(RecommendedAppsService.APP_NAMES); - } - - '__on_boot.consolidation' () { - const svc_appIcon = this.services.get('app-icon'); - const svc_event = this.services.get('event'); - svc_event.on('apps.invalidate', async (_, { app }) => { - const sizes = svc_appIcon.getSizes(); - - // If it's a single-app invalidation, only invalidate if the - // app is in the list of recommended apps - if ( app ) { - const name = app.name; - if ( ! this.app_names.has(name) ) return; - } - - const keys = [RecommendedAppsRedisCacheSpace.key()]; - for ( const size of sizes ) { - const key = RecommendedAppsRedisCacheSpace.key({ iconSize: size }); - keys.push(key); - } - await deleteRedisKeys(keys); - }); - } + ]); async get_recommended_apps ({ icon_size: iconSize }) { - const recommendedCacheKey = RecommendedAppsRedisCacheSpace.key({ iconSize }); - - const cachedRecommended = await redisClient.get(recommendedCacheKey); - if ( cachedRecommended ) { - try { - return JSON.parse(cachedRecommended); - } catch (e) { - // no op cache is in an invalid state - } - } // Prepare each app for returning to user by only returning the necessary fields // and adding them to the retobj array - let recommended = (await get_apps(Array.from(this.app_names).map(name => ({ name })))).filter(app => !!app).map(app => { + let recommended = (await get_apps(Array.from(this.appNames).map(name => ({ name })))).filter(app => !!app).map(app => { return { uuid: app.uid, name: app.name, @@ -108,10 +68,6 @@ export default class RecommendedAppsService extends BaseService { }); } - await setRedisCacheValue(recommendedCacheKey, JSON.stringify(recommended), { - eventData: recommended, - }); - return recommended; } }