forked from tsai/budibase
6 changed files with 199 additions and 180 deletions
@ -0,0 +1,17 @@ |
|||||
|
export enum ContextKeys { |
||||
|
TENANT_ID = "tenantId", |
||||
|
GLOBAL_DB = "globalDb", |
||||
|
APP_ID = "appId", |
||||
|
IDENTITY = "identity", |
||||
|
// whatever the request app DB was
|
||||
|
CURRENT_DB = "currentDb", |
||||
|
// get the prod app DB from the request
|
||||
|
PROD_DB = "prodDb", |
||||
|
// get the dev app DB from the request
|
||||
|
DEV_DB = "devDb", |
||||
|
DB_OPTS = "dbOpts", |
||||
|
// check if something else is using the context, don't close DB
|
||||
|
TENANCY_IN_USE = "tenancyInUse", |
||||
|
APP_IN_USE = "appInUse", |
||||
|
IDENTITY_IN_USE = "identityInUse", |
||||
|
} |
||||
@ -0,0 +1,113 @@ |
|||||
|
import { |
||||
|
DEFAULT_TENANT_ID, |
||||
|
getAppId, |
||||
|
getTenantIDFromAppID, |
||||
|
updateTenantId, |
||||
|
} from "./index" |
||||
|
import cls from "./FunctionContext" |
||||
|
import { IdentityContext } from "@budibase/types" |
||||
|
import { ContextKeys } from "./constants" |
||||
|
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) => { |
||||
|
cls.setOnContext(ContextKeys.IDENTITY, identity) |
||||
|
} |
||||
|
|
||||
|
// this function makes sure the PouchDB objects are closed and
|
||||
|
// fully deleted when finished - this protects against memory leaks
|
||||
|
export async function closeAppDBs() { |
||||
|
const dbKeys = [ |
||||
|
ContextKeys.CURRENT_DB, |
||||
|
ContextKeys.PROD_DB, |
||||
|
ContextKeys.DEV_DB, |
||||
|
] |
||||
|
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
|
||||
|
if (cls.getFromContext(ContextKeys.APP_ID)) { |
||||
|
cls.setOnContext(ContextKeys.APP_ID, null) |
||||
|
} |
||||
|
if (cls.getFromContext(ContextKeys.DB_OPTS)) { |
||||
|
cls.setOnContext(ContextKeys.DB_OPTS, null) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
export function getContextDB(key: string, opts: any) { |
||||
|
const dbOptsKey = `${key}${ContextKeys.DB_OPTS}` |
||||
|
let storedOpts = cls.getFromContext(dbOptsKey) |
||||
|
let db = cls.getFromContext(key) |
||||
|
if (db && isEqual(opts, storedOpts)) { |
||||
|
return db |
||||
|
} |
||||
|
|
||||
|
const appId = getAppId() |
||||
|
let toUseAppId |
||||
|
|
||||
|
switch (key) { |
||||
|
case ContextKeys.CURRENT_DB: |
||||
|
toUseAppId = appId |
||||
|
break |
||||
|
case ContextKeys.PROD_DB: |
||||
|
toUseAppId = getProdAppID(appId) |
||||
|
break |
||||
|
case ContextKeys.DEV_DB: |
||||
|
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 |
||||
|
} |
||||
Loading…
Reference in new issue