From 9483712c7ef7863a16f0e18f26e36202ef0def68 Mon Sep 17 00:00:00 2001 From: Martin McKeaveney Date: Mon, 23 May 2022 00:09:03 +0100 Subject: [PATCH] withCache wrapper for working with redis --- packages/backend-core/src/redis/utils.js | 1 + .../src/api/controllers/global/configs.js | 100 ++++++++++-------- packages/worker/src/utilities/redis.js | 24 ++++- 3 files changed, 77 insertions(+), 48 deletions(-) diff --git a/packages/backend-core/src/redis/utils.js b/packages/backend-core/src/redis/utils.js index 77f64f6593..c2bb59813b 100644 --- a/packages/backend-core/src/redis/utils.js +++ b/packages/backend-core/src/redis/utils.js @@ -18,6 +18,7 @@ exports.Databases = { APP_METADATA: "appMetadata", QUERY_VARS: "queryVars", LICENSES: "license", + DATA_CACHE: "data_cache", } exports.SEPARATOR = SEPARATOR diff --git a/packages/worker/src/api/controllers/global/configs.js b/packages/worker/src/api/controllers/global/configs.js index 3799337bd5..571e102e4c 100644 --- a/packages/worker/src/api/controllers/global/configs.js +++ b/packages/worker/src/api/controllers/global/configs.js @@ -14,6 +14,7 @@ const { const { getGlobalDB, getTenantId } = require("@budibase/backend-core/tenancy") const env = require("../../../environment") const { googleCallbackUrl, oidcCallbackUrl } = require("./auth") +const { withCache } = require("../../../utilities/redis") const BB_TENANT_CDN = "https://tenants.cdn.budi.live" @@ -249,59 +250,64 @@ exports.configChecklist = async function (ctx) { const tenantId = getTenantId() try { - // TODO: Watch get started video + const ONE_MINUTE = 600 - let apps = [] - if (!env.MULTI_TENANCY || tenantId) { - // Apps exist - apps = await getAllApps({ idsOnly: true, efficient: true }) - } + ctx.body = await withCache( + `checklist:${tenantId}`, + ONE_MINUTE, + async () => { + let apps = [] + if (!env.MULTI_TENANCY || tenantId) { + // Apps exist + apps = await getAllApps({ idsOnly: true, efficient: true }) + } - // They have set up SMTP - const smtpConfig = await getScopedFullConfig(db, { - type: Configs.SMTP, - }) + // They have set up SMTP + const smtpConfig = await getScopedFullConfig(db, { + type: Configs.SMTP, + }) - // They have set up Google Auth - const googleConfig = await getScopedFullConfig(db, { - type: Configs.GOOGLE, - }) + // They have set up Google Auth + const googleConfig = await getScopedFullConfig(db, { + type: Configs.GOOGLE, + }) - // They have set up OIDC - const oidcConfig = await getScopedFullConfig(db, { - type: Configs.OIDC, - }) + // They have set up OIDC + const oidcConfig = await getScopedFullConfig(db, { + type: Configs.OIDC, + }) - // They have set up an global user - const users = await db.allDocs( - getGlobalUserParams(null, { - include_docs: true, - limit: 1, - }) + // They have set up an global user + const users = await db.allDocs( + getGlobalUserParams(null, { + include_docs: true, + limit: 1, + }) + ) + return { + apps: { + checked: apps.length > 0, + label: "Create your first app", + link: "/builder/portal/apps", + }, + smtp: { + checked: !!smtpConfig, + label: "Set up email", + link: "/builder/portal/manage/email", + }, + adminUser: { + checked: users && users.rows.length >= 1, + label: "Create your first user", + link: "/builder/portal/manage/users", + }, + sso: { + checked: !!googleConfig || !!oidcConfig, + label: "Set up single sign-on", + link: "/builder/portal/manage/auth", + }, + } + } ) - - ctx.body = { - apps: { - checked: apps.length > 0, - label: "Create your first app", - link: "/builder/portal/apps", - }, - smtp: { - checked: !!smtpConfig, - label: "Set up email", - link: "/builder/portal/manage/email", - }, - adminUser: { - checked: users && users.rows.length >= 1, - label: "Create your first user", - link: "/builder/portal/manage/users", - }, - sso: { - checked: !!googleConfig || !!oidcConfig, - label: "Set up single sign-on", - link: "/builder/portal/manage/auth", - }, - } } catch (err) { ctx.throw(err.status, err) } diff --git a/packages/worker/src/utilities/redis.js b/packages/worker/src/utilities/redis.js index cfed97cd18..70a16a3be8 100644 --- a/packages/worker/src/utilities/redis.js +++ b/packages/worker/src/utilities/redis.js @@ -12,7 +12,7 @@ function getExpirySecondsForDB(db) { } } -let pwResetClient, invitationClient +let pwResetClient, invitationClient, cachingClient function getClient(db) { switch (db) { @@ -20,6 +20,8 @@ function getClient(db) { return pwResetClient case utils.Databases.INVITATIONS: return invitationClient + case utils.Databases.DATA_CACHE: + return cachingClient } } @@ -45,8 +47,10 @@ async function getACode(db, code, deleteCode = true) { exports.init = async () => { pwResetClient = new Client(utils.Databases.PW_RESETS) invitationClient = new Client(utils.Databases.INVITATIONS) + cachingClient = new Client(utils.Databases.DATA_CACHE) await pwResetClient.init() await invitationClient.init() + await cachingClient.init() } /** @@ -104,3 +108,21 @@ exports.checkInviteCode = async (inviteCode, deleteCode = true) => { throw "Invitation is not valid or has expired, please request a new one." } } + +// TODO: move into backend-core +exports.withCache = async (key, ttl, fetchFn) => { + const cachedValue = await cachingClient.get(key) + if (cachedValue) { + return cachedValue + } + + try { + const fetchedValue = await fetchFn() + + await cachingClient.store(key, fetchedValue, ttl) + return fetchedValue + } catch (err) { + console.error("Error calling fetch function", err) + throw err + } +}