1
0
Fork 0
mirror of synced 2024-06-30 03:50:37 +12:00
budibase/packages/backend-core/src/migrations/index.js

104 lines
3 KiB
JavaScript
Raw Normal View History

2022-01-24 23:48:59 +13:00
const { DEFAULT_TENANT_ID } = require("../constants")
2021-10-27 00:40:30 +13:00
const { DocumentTypes } = require("../db/constants")
2022-01-24 23:48:59 +13:00
const { getAllApps } = require("../db/utils")
const environment = require("../environment")
const { doInTenant, getTenantIds, getGlobalDBName } = require("../tenancy")
2021-10-27 00:40:30 +13:00
2022-01-24 23:48:59 +13:00
exports.MIGRATION_TYPES = {
GLOBAL: "global", // run once, recorded in global db, global db is provided as an argument
APP: "app", // run per app, recorded in each app db, app db is provided as an argument
2021-10-27 00:40:30 +13:00
}
2021-10-27 03:47:36 +13:00
exports.getMigrationsDoc = async db => {
2021-10-27 00:40:30 +13:00
// get the migrations doc
try {
return await db.get(DocumentTypes.MIGRATIONS)
} catch (err) {
if (err.status && err.status === 404) {
return { _id: DocumentTypes.MIGRATIONS }
}
}
}
2022-01-24 23:48:59 +13:00
const runMigration = async (tenantId, CouchDB, migration, options = {}) => {
const migrationType = migration.type
const migrationName = migration.name
// get the db to store the migration in
let dbNames
if (migrationType === exports.MIGRATION_TYPES.GLOBAL) {
dbNames = [getGlobalDBName(tenantId)]
} else if (migrationType === exports.MIGRATION_TYPES.APP) {
dbNames = await getAllApps(CouchDB, { all: true })
} else {
throw new Error(
`[Tenant: ${tenantId}] Unrecognised migration type [${migrationType}]`
)
}
// run the migration against each db
for (const dbName of dbNames) {
const db = new CouchDB(dbName)
try {
const doc = await exports.getMigrationsDoc(db)
2021-10-27 03:47:36 +13:00
2022-01-24 23:48:59 +13:00
// exit if the migration has been performed already
if (doc[migrationName]) {
if (
options.force &&
options.force[migrationType] &&
options.force[migrationType].includes(migrationName)
) {
console.log(
`[Tenant: ${tenantId}] Forcing migration [${migrationName}]`
)
} else {
// the migration has already been performed
return
}
}
console.log(
`[Tenant: ${tenantId}] Performing migration: ${migrationName}`
2021-10-27 03:47:36 +13:00
)
2022-01-24 23:48:59 +13:00
// run the migration with tenant context
await doInTenant(tenantId, () => migration.fn(db))
console.log(`[Tenant: ${tenantId}] Migration complete: ${migrationName}`)
2021-10-27 00:40:30 +13:00
2022-01-24 23:48:59 +13:00
// mark as complete
doc[migrationName] = Date.now()
await db.put(doc)
} catch (err) {
console.error(
`[Tenant: ${tenantId}] Error performing migration: ${migrationName} on db: ${db.name}: `,
err
)
throw err
2021-10-27 00:40:30 +13:00
}
2022-01-24 23:48:59 +13:00
}
}
2021-10-27 00:40:30 +13:00
2022-01-24 23:48:59 +13:00
exports.runMigrations = async (CouchDB, migrations, options = {}) => {
console.log("Running migrations")
let tenantIds
if (environment.MULTI_TENANCY) {
if (!options.tenantIds || !options.tenantIds.length) {
// run for all tenants
tenantIds = await getTenantIds()
}
} else {
// single tenancy
tenantIds = [DEFAULT_TENANT_ID]
}
2021-10-27 00:40:30 +13:00
2022-01-24 23:48:59 +13:00
// for all tenants
for (const tenantId of tenantIds) {
// for all migrations
for (const migration of migrations) {
// run the migration
await runMigration(tenantId, CouchDB, migration, options)
}
2021-10-27 00:40:30 +13:00
}
2022-01-24 23:48:59 +13:00
console.log("Migrations complete")
2021-10-27 00:40:30 +13:00
}