2022-07-14 17:02:05 +02:00
|
|
|
import {
|
|
|
|
DEFAULT_TENANT_ID,
|
|
|
|
getAppId,
|
|
|
|
getTenantIDFromAppID,
|
|
|
|
updateTenantId,
|
|
|
|
} from "./index"
|
|
|
|
import cls from "./FunctionContext"
|
|
|
|
import { IdentityContext } from "@budibase/types"
|
2022-08-11 14:50:05 +02:00
|
|
|
import { ContextKey } from "./constants"
|
2022-07-14 17:02:05 +02:00
|
|
|
import { dangerousGetDB, closeDB } from "../db"
|
|
|
|
import { isEqual } from "lodash"
|
|
|
|
import { getDevelopmentAppID, getProdAppID } from "../db/conversions"
|
|
|
|
import env from "../environment"
|
|
|
|
|
|
|
|
export async function updateUsing(
|
|
|
|
usingKey: string,
|
|
|
|
existing: boolean,
|
|
|
|
internal: (opts: { existing: boolean }) => Promise<any>
|
|
|
|
) {
|
|
|
|
const using = cls.getFromContext(usingKey)
|
|
|
|
if (using && existing) {
|
|
|
|
cls.setOnContext(usingKey, using + 1)
|
|
|
|
return internal({ existing: true })
|
|
|
|
} else {
|
|
|
|
return cls.run(async () => {
|
|
|
|
cls.setOnContext(usingKey, 1)
|
|
|
|
return internal({ existing: false })
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export async function closeWithUsing(
|
|
|
|
usingKey: string,
|
|
|
|
closeFn: () => Promise<any>
|
|
|
|
) {
|
|
|
|
const using = cls.getFromContext(usingKey)
|
|
|
|
if (!using || using <= 1) {
|
|
|
|
await closeFn()
|
|
|
|
} else {
|
|
|
|
cls.setOnContext(usingKey, using - 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export const setAppTenantId = (appId: string) => {
|
|
|
|
const appTenantId = getTenantIDFromAppID(appId) || DEFAULT_TENANT_ID
|
|
|
|
updateTenantId(appTenantId)
|
|
|
|
}
|
|
|
|
|
|
|
|
export const setIdentity = (identity: IdentityContext | null) => {
|
2022-08-11 14:50:05 +02:00
|
|
|
cls.setOnContext(ContextKey.IDENTITY, identity)
|
2022-07-14 17:02:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// this function makes sure the PouchDB objects are closed and
|
|
|
|
// fully deleted when finished - this protects against memory leaks
|
|
|
|
export async function closeAppDBs() {
|
2022-08-11 14:50:05 +02:00
|
|
|
const dbKeys = [ContextKey.CURRENT_DB, ContextKey.PROD_DB, ContextKey.DEV_DB]
|
2022-07-14 17:02:05 +02:00
|
|
|
for (let dbKey of dbKeys) {
|
|
|
|
const db = cls.getFromContext(dbKey)
|
|
|
|
if (!db) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
await closeDB(db)
|
|
|
|
// clear the DB from context, incase someone tries to use it again
|
|
|
|
cls.setOnContext(dbKey, null)
|
|
|
|
}
|
|
|
|
// clear the app ID now that the databases are closed
|
2022-08-11 14:50:05 +02:00
|
|
|
if (cls.getFromContext(ContextKey.APP_ID)) {
|
|
|
|
cls.setOnContext(ContextKey.APP_ID, null)
|
2022-07-14 17:02:05 +02:00
|
|
|
}
|
2022-08-11 14:50:05 +02:00
|
|
|
if (cls.getFromContext(ContextKey.DB_OPTS)) {
|
|
|
|
cls.setOnContext(ContextKey.DB_OPTS, null)
|
2022-07-14 17:02:05 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export function getContextDB(key: string, opts: any) {
|
2022-08-11 14:50:05 +02:00
|
|
|
const dbOptsKey = `${key}${ContextKey.DB_OPTS}`
|
2022-07-14 17:02:05 +02:00
|
|
|
let storedOpts = cls.getFromContext(dbOptsKey)
|
|
|
|
let db = cls.getFromContext(key)
|
|
|
|
if (db && isEqual(opts, storedOpts)) {
|
|
|
|
return db
|
|
|
|
}
|
|
|
|
|
|
|
|
const appId = getAppId()
|
|
|
|
let toUseAppId
|
|
|
|
|
|
|
|
switch (key) {
|
2022-08-11 14:50:05 +02:00
|
|
|
case ContextKey.CURRENT_DB:
|
2022-07-14 17:02:05 +02:00
|
|
|
toUseAppId = appId
|
|
|
|
break
|
2022-08-11 14:50:05 +02:00
|
|
|
case ContextKey.PROD_DB:
|
2022-07-14 17:02:05 +02:00
|
|
|
toUseAppId = getProdAppID(appId)
|
|
|
|
break
|
2022-08-11 14:50:05 +02:00
|
|
|
case ContextKey.DEV_DB:
|
2022-07-14 17:02:05 +02:00
|
|
|
toUseAppId = getDevelopmentAppID(appId)
|
|
|
|
break
|
|
|
|
}
|
|
|
|
db = dangerousGetDB(toUseAppId, opts)
|
|
|
|
try {
|
|
|
|
cls.setOnContext(key, db)
|
|
|
|
if (opts) {
|
|
|
|
cls.setOnContext(dbOptsKey, opts)
|
|
|
|
}
|
|
|
|
} catch (err) {
|
|
|
|
if (!env.isTest()) {
|
|
|
|
throw err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return db
|
|
|
|
}
|