2022-11-24 19:48:51 +01:00
|
|
|
import { getAppClient } from "../redis/init"
|
|
|
|
import { doWithDB, DocumentType } from "../db"
|
2023-03-02 11:20:49 +01:00
|
|
|
import { Database, App } from "@budibase/types"
|
2021-11-15 18:40:45 +01:00
|
|
|
|
2023-07-20 17:15:59 +02:00
|
|
|
export enum AppState {
|
2023-07-20 17:56:31 +02:00
|
|
|
INVALID = "invalid",
|
2021-11-16 15:15:13 +01:00
|
|
|
}
|
2023-07-21 10:57:37 +02:00
|
|
|
|
|
|
|
export interface DeletedApp {
|
|
|
|
state: AppState
|
|
|
|
}
|
|
|
|
|
2021-11-15 18:40:45 +01:00
|
|
|
const EXPIRY_SECONDS = 3600
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The default populate app metadata function
|
|
|
|
*/
|
2022-11-24 19:48:51 +01:00
|
|
|
async function populateFromDB(appId: string) {
|
2022-04-19 20:42:52 +02:00
|
|
|
return doWithDB(
|
|
|
|
appId,
|
2022-11-24 19:48:51 +01:00
|
|
|
(db: Database) => {
|
2022-08-11 14:50:05 +02:00
|
|
|
return db.get(DocumentType.APP_METADATA)
|
2022-04-19 20:42:52 +02:00
|
|
|
},
|
|
|
|
{ skip_setup: true }
|
|
|
|
)
|
2021-11-15 18:40:45 +01:00
|
|
|
}
|
|
|
|
|
2022-11-24 19:48:51 +01:00
|
|
|
function isInvalid(metadata?: { state: string }) {
|
2021-11-16 18:40:31 +01:00
|
|
|
return !metadata || metadata.state === AppState.INVALID
|
|
|
|
}
|
|
|
|
|
2021-11-15 18:40:45 +01:00
|
|
|
/**
|
|
|
|
* Get the requested app metadata by id.
|
|
|
|
* Use redis cache to first read the app metadata.
|
|
|
|
* If not present fallback to loading the app metadata directly and re-caching.
|
2021-11-16 18:40:31 +01:00
|
|
|
* @param {string} appId the id of the app to get metadata from.
|
2021-11-15 18:40:45 +01:00
|
|
|
* @returns {object} the app metadata.
|
|
|
|
*/
|
2023-07-21 10:57:37 +02:00
|
|
|
export async function getAppMetadata(appId: string): Promise<App | DeletedApp> {
|
2022-11-24 19:48:51 +01:00
|
|
|
const client = await getAppClient()
|
2021-11-15 18:40:45 +01:00
|
|
|
// try cache
|
|
|
|
let metadata = await client.get(appId)
|
|
|
|
if (!metadata) {
|
2022-11-24 19:48:51 +01:00
|
|
|
let expiry: number | undefined = EXPIRY_SECONDS
|
2021-11-16 15:15:13 +01:00
|
|
|
try {
|
2022-03-29 17:03:44 +02:00
|
|
|
metadata = await populateFromDB(appId)
|
2022-11-24 19:48:51 +01:00
|
|
|
} catch (err: any) {
|
2021-11-16 15:15:13 +01:00
|
|
|
// app DB left around, but no metadata, it is invalid
|
|
|
|
if (err && err.status === 404) {
|
|
|
|
metadata = { state: AppState.INVALID }
|
|
|
|
// don't expire the reference to an invalid app, it'll only be
|
|
|
|
// updated if a metadata doc actually gets stored (app is remade/reverted)
|
|
|
|
expiry = undefined
|
|
|
|
} else {
|
|
|
|
throw err
|
|
|
|
}
|
|
|
|
}
|
2021-11-16 18:40:31 +01:00
|
|
|
// needed for cypress/some scenarios where the caching happens
|
|
|
|
// so quickly the requests can get slightly out of sync
|
|
|
|
// might store its invalid just before it stores its valid
|
|
|
|
if (isInvalid(metadata)) {
|
|
|
|
const temp = await client.get(appId)
|
|
|
|
if (temp) {
|
|
|
|
metadata = temp
|
|
|
|
}
|
|
|
|
}
|
2021-11-16 16:23:02 +01:00
|
|
|
await client.store(appId, metadata, expiry)
|
2021-11-16 15:15:13 +01:00
|
|
|
}
|
2023-07-20 17:15:59 +02:00
|
|
|
|
2023-07-21 10:43:25 +02:00
|
|
|
return metadata
|
2021-11-15 18:40:45 +01:00
|
|
|
}
|
|
|
|
|
2021-11-16 21:56:24 +01:00
|
|
|
/**
|
|
|
|
* Invalidate/reset the cached metadata when a change occurs in the db.
|
|
|
|
* @param appId {string} the cache key to bust/update.
|
|
|
|
* @param newMetadata {object|undefined} optional - can simply provide the new metadata to update with.
|
|
|
|
* @return {Promise<void>} will respond with success when cache is updated.
|
|
|
|
*/
|
2022-11-24 19:48:51 +01:00
|
|
|
export async function invalidateAppMetadata(appId: string, newMetadata?: any) {
|
2021-11-16 21:56:24 +01:00
|
|
|
if (!appId) {
|
|
|
|
throw "Cannot invalidate if no app ID provided."
|
|
|
|
}
|
2022-11-24 19:48:51 +01:00
|
|
|
const client = await getAppClient()
|
2021-11-15 18:40:45 +01:00
|
|
|
await client.delete(appId)
|
2021-11-16 21:56:24 +01:00
|
|
|
if (newMetadata) {
|
|
|
|
await client.store(appId, newMetadata, EXPIRY_SECONDS)
|
|
|
|
}
|
2021-11-15 18:40:45 +01:00
|
|
|
}
|