Merge pull request #15657 from Budibase/fix/app-deletion-issue

Fix app deletion issue in development
This commit is contained in:
Michael Drury 2025-03-03 14:30:29 +00:00 committed by GitHub
commit 4b44ab50e4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 29 additions and 11 deletions

View File

@ -478,7 +478,7 @@ export async function deleteFolder(
if (existingObjectsResponse.Contents?.length === 0) { if (existingObjectsResponse.Contents?.length === 0) {
return return
} }
const deleteParams: any = { const deleteParams: { Bucket: string; Delete: { Objects: any[] } } = {
Bucket: bucketName, Bucket: bucketName,
Delete: { Delete: {
Objects: [], Objects: [],
@ -489,10 +489,12 @@ export async function deleteFolder(
deleteParams.Delete.Objects.push({ Key: content.Key }) deleteParams.Delete.Objects.push({ Key: content.Key })
}) })
const deleteResponse = await client.deleteObjects(deleteParams) if (deleteParams.Delete.Objects.length) {
// can only empty 1000 items at once const deleteResponse = await client.deleteObjects(deleteParams)
if (deleteResponse.Deleted?.length === 1000) { // can only empty 1000 items at once
return deleteFolder(bucketName, folder) if (deleteResponse.Deleted?.length === 1000) {
return deleteFolder(bucketName, folder)
}
} }
} }

View File

@ -635,6 +635,11 @@ async function unpublishApp(ctx: UserCtx) {
return result return result
} }
async function invalidateAppCache(appId: string) {
await cache.app.invalidateAppMetadata(dbCore.getDevAppID(appId))
await cache.app.invalidateAppMetadata(dbCore.getProdAppID(appId))
}
async function destroyApp(ctx: UserCtx) { async function destroyApp(ctx: UserCtx) {
let appId = ctx.params.appId let appId = ctx.params.appId
appId = dbCore.getProdAppID(appId) appId = dbCore.getProdAppID(appId)
@ -654,17 +659,21 @@ async function destroyApp(ctx: UserCtx) {
await quotas.removeApp() await quotas.removeApp()
await events.app.deleted(app) await events.app.deleted(app)
if (!env.isTest()) { if (!env.USE_LOCAL_COMPONENT_LIBS) {
await deleteAppFiles(appId) await deleteAppFiles(appId)
} }
await removeAppFromUserRoles(ctx, appId) await removeAppFromUserRoles(ctx, appId)
await cache.app.invalidateAppMetadata(devAppId) await invalidateAppCache(appId)
return result return result
} }
async function preDestroyApp(ctx: UserCtx) { async function preDestroyApp(ctx: UserCtx) {
const { rows } = await getUniqueRows([ctx.params.appId]) // invalidate the cache immediately in-case they are leading to
// zombie appearing apps
const appId = ctx.params.appId
await invalidateAppCache(appId)
const { rows } = await getUniqueRows([appId])
ctx.rowCount = rows.length ctx.rowCount = rows.length
} }

View File

@ -1,4 +1,5 @@
import { DEFAULT_TABLES } from "../../../db/defaultData/datasource_bb_default" import { DEFAULT_TABLES } from "../../../db/defaultData/datasource_bb_default"
import { setEnv } from "../../../environment"
jest.mock("../../../utilities/redis", () => ({ jest.mock("../../../utilities/redis", () => ({
init: jest.fn(), init: jest.fn(),
@ -27,10 +28,16 @@ import path from "path"
describe("/applications", () => { describe("/applications", () => {
let config = setup.getConfig() let config = setup.getConfig()
let app: App let app: App, cleanup: () => void
afterAll(setup.afterAll) afterAll(() => {
beforeAll(async () => await config.init()) setup.afterAll()
cleanup()
})
beforeAll(async () => {
cleanup = setEnv({ USE_LOCAL_COMPONENT_LIBS: "0" })
await config.init()
})
beforeEach(async () => { beforeEach(async () => {
app = await config.api.application.create({ name: utils.newid() }) app = await config.api.application.create({ name: utils.newid() })