forked from tsai/budibase
committed by
GitHub
9 changed files with 138 additions and 12 deletions
@ -0,0 +1,13 @@ |
|||||
|
const { migrate, MIGRATIONS } = require("../../../migrations") |
||||
|
|
||||
|
export const runMigrations = async (ctx: any) => { |
||||
|
const options = ctx.request.body |
||||
|
// don't await as can take a while, just return
|
||||
|
migrate(options) |
||||
|
ctx.status = 200 |
||||
|
} |
||||
|
|
||||
|
export const fetchDefinitions = async (ctx: any) => { |
||||
|
ctx.body = MIGRATIONS |
||||
|
ctx.status = 200 |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
import Router from "@koa/router" |
||||
|
import * as migrationsController from "../../controllers/system/migrations" |
||||
|
import { auth } from "@budibase/backend-core" |
||||
|
|
||||
|
const router = new Router() |
||||
|
|
||||
|
router |
||||
|
.post( |
||||
|
"/api/system/migrations/run", |
||||
|
auth.internalApi, |
||||
|
migrationsController.runMigrations |
||||
|
) |
||||
|
.get( |
||||
|
"/api/system/migrations/definitions", |
||||
|
auth.internalApi, |
||||
|
migrationsController.fetchDefinitions |
||||
|
) |
||||
|
|
||||
|
export = router |
||||
@ -0,0 +1,20 @@ |
|||||
|
import { User } from "@budibase/types" |
||||
|
import * as sdk from "../../sdk" |
||||
|
|
||||
|
/** |
||||
|
* Date: |
||||
|
* Aug 2022 |
||||
|
* |
||||
|
* Description: |
||||
|
* Re-sync the global-db users to the global-info db users |
||||
|
*/ |
||||
|
export const run = async (globalDb: any) => { |
||||
|
const users = (await sdk.users.allUsers()) as User[] |
||||
|
const promises = [] |
||||
|
for (let user of users) { |
||||
|
promises.push( |
||||
|
sdk.users.addTenant(user.tenantId, user._id as string, user.email) |
||||
|
) |
||||
|
} |
||||
|
await Promise.all(promises) |
||||
|
} |
||||
@ -0,0 +1,74 @@ |
|||||
|
import { migrations, redis } from "@budibase/backend-core" |
||||
|
import { Migration, MigrationOptions, MigrationName } from "@budibase/types" |
||||
|
import env from "../environment" |
||||
|
|
||||
|
// migration functions
|
||||
|
import * as syncUserInfo from "./functions/globalInfoSyncUsers" |
||||
|
|
||||
|
/** |
||||
|
* Populate the migration function and additional configuration from |
||||
|
* the static migration definitions. |
||||
|
*/ |
||||
|
export const buildMigrations = () => { |
||||
|
const definitions = migrations.DEFINITIONS |
||||
|
const workerMigrations: Migration[] = [] |
||||
|
|
||||
|
for (const definition of definitions) { |
||||
|
switch (definition.name) { |
||||
|
case MigrationName.GLOBAL_INFO_SYNC_USERS: { |
||||
|
// only needed in cloud
|
||||
|
if (!env.SELF_HOSTED) { |
||||
|
workerMigrations.push({ |
||||
|
...definition, |
||||
|
fn: syncUserInfo.run, |
||||
|
}) |
||||
|
} |
||||
|
break |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return workerMigrations |
||||
|
} |
||||
|
|
||||
|
export const MIGRATIONS = buildMigrations() |
||||
|
|
||||
|
export const migrate = async (options?: MigrationOptions) => { |
||||
|
if (env.SELF_HOSTED) { |
||||
|
await migrateWithLock(options) |
||||
|
} else { |
||||
|
await migrations.runMigrations(MIGRATIONS, options) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const migrateWithLock = async (options?: MigrationOptions) => { |
||||
|
// get a new lock client
|
||||
|
const redlock = await redis.clients.getMigrationsRedlock() |
||||
|
// lock for 15 minutes
|
||||
|
const ttl = 1000 * 60 * 15 |
||||
|
|
||||
|
let migrationLock |
||||
|
|
||||
|
// acquire lock
|
||||
|
try { |
||||
|
migrationLock = await redlock.lock("migrations", ttl) |
||||
|
} catch (e: any) { |
||||
|
if (e.name === "LockError") { |
||||
|
return |
||||
|
} else { |
||||
|
throw e |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// run migrations
|
||||
|
try { |
||||
|
await migrations.runMigrations(MIGRATIONS, options) |
||||
|
} finally { |
||||
|
// release lock
|
||||
|
try { |
||||
|
await migrationLock.unlock() |
||||
|
} catch (e) { |
||||
|
console.error("unable to release migration lock") |
||||
|
} |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue