From 2c40394bc62146fc2cc632747a8e10479d10fb0e Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Fri, 7 Oct 2022 16:05:01 +0100 Subject: [PATCH] Switching from scan for app locks to mget - which is a fast O(N) operation that only retrieves what we need. --- packages/backend-core/src/redis/index.ts | 25 +++++++++++++++++++ .../server/src/api/controllers/application.ts | 17 ++++++------- packages/server/src/utilities/redis.js | 8 ++---- 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/packages/backend-core/src/redis/index.ts b/packages/backend-core/src/redis/index.ts index 206110366f..62e718d8ad 100644 --- a/packages/backend-core/src/redis/index.ts +++ b/packages/backend-core/src/redis/index.ts @@ -214,6 +214,31 @@ export = class RedisWrapper { } } + async bulkGet(keys: string[]) { + const db = this._db + const prefixedKeys = keys.map(key => addDbPrefix(db, key)) + let response = await this.getClient().mget(prefixedKeys) + if (Array.isArray(response)) { + let final: any = {} + let count = 0 + for (let result of response) { + if (result) { + let parsed + try { + parsed = JSON.parse(result) + } catch (err) { + parsed = result + } + final[keys[count]] = parsed + } + count++ + } + return final + } else { + throw new Error(`Invalid response: ${response}`) + } + } + async store(key: string, value: any, expirySeconds: number | null = null) { const db = this._db if (typeof value === "object") { diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index b6377a61a2..e8af2f54f8 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -32,7 +32,7 @@ const { import { USERS_TABLE_SCHEMA } from "../../constants" import { removeAppFromUserRoles } from "../../utilities/workerRequests" import { clientLibraryPath, stringToReadStream } from "../../utilities" -import { getAllLocks } from "../../utilities/redis" +import { getLocksById } from "../../utilities/redis" import { updateClientLibrary, backupClientLibrary, @@ -45,11 +45,10 @@ import { cleanupAutomations } from "../../automations/utils" import { context } from "@budibase/backend-core" import { checkAppMetadata } from "../../automations/logging" import { getUniqueRows } from "../../utilities/usageQuota/rows" -import { quotas } from "@budibase/pro" +import { quotas, groups } from "@budibase/pro" import { errors, events, migrations } from "@budibase/backend-core" import { App, Layout, Screen, MigrationType } from "@budibase/types" import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts" -import { groups } from "@budibase/pro" import { enrichPluginURLs } from "../../utilities/plugins" const URL_REGEX_SLASH = /\/|\\/g @@ -172,16 +171,16 @@ export const fetch = async (ctx: any) => { const all = ctx.query && ctx.query.status === AppStatus.ALL const apps = await getAllApps({ dev, all }) + const appIds = apps + .filter((app: any) => app.status === "development") + .map((app: any) => app.appId) // get the locks for all the dev apps if (dev || all) { - const locks = await getAllLocks() + const locks = await getLocksById(appIds) for (let app of apps) { - if (app.status !== "development") { - continue - } - const lock = locks.find((lock: any) => lock.appId === app.appId) + const lock = locks[app.appId] if (lock) { - app.lockedBy = lock.user + app.lockedBy = lock } else { // make sure its definitely not present delete app.lockedBy diff --git a/packages/server/src/utilities/redis.js b/packages/server/src/utilities/redis.js index 4eddca6e4a..b39b7cae55 100644 --- a/packages/server/src/utilities/redis.js +++ b/packages/server/src/utilities/redis.js @@ -34,12 +34,8 @@ exports.doesUserHaveLock = async (devAppId, user) => { return expected === userId } -exports.getAllLocks = async () => { - const locks = await devAppClient.scan() - return locks.map(lock => ({ - appId: lock.key, - user: lock.value, - })) +exports.getLocksById = async appIds => { + return await devAppClient.bulkGet(appIds) } exports.updateLock = async (devAppId, user) => {