Fixing an issue with multi-tenant app migration failures - the app migration context wasn't getting the tenant ID as needed. Also added some better logging as well as cleaning up the queues properly to remove these dud events.
This commit is contained in:
parent
67c6c156e3
commit
ee391b30d6
|
@ -21,6 +21,7 @@ let cleanupInterval: NodeJS.Timeout
|
||||||
async function cleanup() {
|
async function cleanup() {
|
||||||
for (let queue of QUEUES) {
|
for (let queue of QUEUES) {
|
||||||
await queue.clean(CLEANUP_PERIOD_MS, "completed")
|
await queue.clean(CLEANUP_PERIOD_MS, "completed")
|
||||||
|
await queue.clean(CLEANUP_PERIOD_MS, "failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -48,8 +48,6 @@ export async function checkMissingMigrations(
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
jobId: `${appId}_${latestMigration}`,
|
jobId: `${appId}_${latestMigration}`,
|
||||||
removeOnComplete: true,
|
|
||||||
removeOnFail: true,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -12,54 +12,56 @@ export async function processMigrations(
|
||||||
migrations: AppMigration[]
|
migrations: AppMigration[]
|
||||||
) {
|
) {
|
||||||
console.log(`Processing app migration for "${appId}"`)
|
console.log(`Processing app migration for "${appId}"`)
|
||||||
|
// have to wrap in context, this gets the tenant from the app ID
|
||||||
await locks.doWithLock(
|
await context.doInAppContext(appId, async () => {
|
||||||
{
|
await locks.doWithLock(
|
||||||
name: LockName.APP_MIGRATION,
|
{
|
||||||
type: LockType.AUTO_EXTEND,
|
name: LockName.APP_MIGRATION,
|
||||||
resource: appId,
|
type: LockType.AUTO_EXTEND,
|
||||||
},
|
resource: appId,
|
||||||
async () => {
|
},
|
||||||
await context.doInAppMigrationContext(appId, async () => {
|
async () => {
|
||||||
try {
|
try {
|
||||||
let currentVersion = await getAppMigrationVersion(appId)
|
await context.doInAppMigrationContext(appId, async () => {
|
||||||
|
let currentVersion = await getAppMigrationVersion(appId)
|
||||||
|
|
||||||
const pendingMigrations = migrations
|
const pendingMigrations = migrations
|
||||||
.filter(m => m.id > currentVersion)
|
.filter(m => m.id > currentVersion)
|
||||||
.sort((a, b) => a.id.localeCompare(b.id))
|
.sort((a, b) => a.id.localeCompare(b.id))
|
||||||
|
|
||||||
const migrationIds = migrations.map(m => m.id).sort()
|
const migrationIds = migrations.map(m => m.id).sort()
|
||||||
|
|
||||||
let index = 0
|
let index = 0
|
||||||
for (const { id, func } of pendingMigrations) {
|
for (const { id, func } of pendingMigrations) {
|
||||||
const expectedMigration =
|
const expectedMigration =
|
||||||
migrationIds[migrationIds.indexOf(currentVersion) + 1]
|
migrationIds[migrationIds.indexOf(currentVersion) + 1]
|
||||||
|
|
||||||
if (expectedMigration !== id) {
|
if (expectedMigration !== id) {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`Migration ${id} could not run, update for "${id}" is running but ${expectedMigration} is expected`
|
`Migration ${id} could not run, update for "${id}" is running but ${expectedMigration} is expected`
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const counter = `(${++index}/${pendingMigrations.length})`
|
||||||
|
console.info(`Running migration ${id}... ${counter}`, {
|
||||||
|
migrationId: id,
|
||||||
|
appId,
|
||||||
|
})
|
||||||
|
await func()
|
||||||
|
await updateAppMigrationMetadata({
|
||||||
|
appId,
|
||||||
|
version: id,
|
||||||
|
})
|
||||||
|
currentVersion = id
|
||||||
}
|
}
|
||||||
|
})
|
||||||
const counter = `(${++index}/${pendingMigrations.length})`
|
|
||||||
console.info(`Running migration ${id}... ${counter}`, {
|
|
||||||
migrationId: id,
|
|
||||||
appId,
|
|
||||||
})
|
|
||||||
await func()
|
|
||||||
await updateAppMigrationMetadata({
|
|
||||||
appId,
|
|
||||||
version: id,
|
|
||||||
})
|
|
||||||
currentVersion = id
|
|
||||||
}
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logging.logAlert("Failed to run app migration", err)
|
logging.logAlert("Failed to run app migration", err)
|
||||||
throw err
|
throw err
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
)
|
||||||
)
|
|
||||||
|
|
||||||
console.log(`App migration for "${appId}" processed`)
|
console.log(`App migration for "${appId}" processed`)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,23 @@
|
||||||
import { queue } from "@budibase/backend-core"
|
import { queue, logging } from "@budibase/backend-core"
|
||||||
import { Job } from "bull"
|
import { Job } from "bull"
|
||||||
import { MIGRATIONS } from "./migrations"
|
import { MIGRATIONS } from "./migrations"
|
||||||
import { processMigrations } from "./migrationsProcessor"
|
import { processMigrations } from "./migrationsProcessor"
|
||||||
|
|
||||||
const appMigrationQueue = queue.createQueue(queue.JobQueue.APP_MIGRATION)
|
const MAX_ATTEMPTS = 3
|
||||||
|
|
||||||
|
const appMigrationQueue = queue.createQueue(queue.JobQueue.APP_MIGRATION, {
|
||||||
|
jobOptions: {
|
||||||
|
attempts: MAX_ATTEMPTS,
|
||||||
|
removeOnComplete: true,
|
||||||
|
removeOnFail: true,
|
||||||
|
},
|
||||||
|
maxStalledCount: MAX_ATTEMPTS,
|
||||||
|
removeStalledCb: async (job: Job) => {
|
||||||
|
logging.logAlert(
|
||||||
|
`App migration failed, queue job ID: ${job.id} - reason: ${job.failedReason}`
|
||||||
|
)
|
||||||
|
},
|
||||||
|
})
|
||||||
appMigrationQueue.process(processMessage)
|
appMigrationQueue.process(processMessage)
|
||||||
|
|
||||||
async function processMessage(job: Job) {
|
async function processMessage(job: Job) {
|
||||||
|
|
Loading…
Reference in New Issue