refactor: Run migrations and links sync after loading the app (#8582)
This commit is contained in:
@@ -1,18 +1,16 @@
|
||||
import express from "express"
|
||||
import getPort from "get-port"
|
||||
import { resolve } from "path"
|
||||
import { isObject, promiseAll, GracefulShutdownServer } from "@medusajs/utils"
|
||||
import { MedusaContainer } from "@medusajs/types"
|
||||
import { applyEnvVarsToProcess } from "./utils"
|
||||
import { promiseAll, GracefulShutdownServer } from "@medusajs/utils"
|
||||
|
||||
async function bootstrapApp({
|
||||
cwd,
|
||||
env = {},
|
||||
}: { cwd?: string; env?: Record<any, any> } = {}) {
|
||||
const app = express()
|
||||
|
||||
if (isObject(env)) {
|
||||
Object.entries(env).forEach(([k, v]) => (process.env[k] = v))
|
||||
}
|
||||
applyEnvVarsToProcess(env)
|
||||
|
||||
const loaders = require("@medusajs/medusa/dist/loaders").default
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* cleanup temporary created resources for the migrations
|
||||
* @internal I didnt find a god place to put that, should we eventually add a close function
|
||||
* to the planner to handle that part? so that you would do planner.close() and it will handle the cleanup
|
||||
* automatically just like we usually do for the classic migrations actions
|
||||
*/
|
||||
export async function clearInstances() {
|
||||
const { MedusaModule } = require("@medusajs/modules-sdk")
|
||||
MedusaModule.clearInstances()
|
||||
}
|
||||
@@ -1,46 +1,46 @@
|
||||
import { ContainerRegistrationKeys, isObject } from "@medusajs/utils"
|
||||
import type { MedusaAppLoader } from "@medusajs/framework"
|
||||
import { ContainerRegistrationKeys } from "@medusajs/utils"
|
||||
import { asValue } from "awilix"
|
||||
|
||||
export async function initDb({ env = {} }: { env?: Record<any, any> }) {
|
||||
if (isObject(env)) {
|
||||
Object.entries(env).forEach(([k, v]) => (process.env[k] = v))
|
||||
}
|
||||
|
||||
const {
|
||||
pgConnectionLoader,
|
||||
logger,
|
||||
container,
|
||||
featureFlagsLoader,
|
||||
MedusaAppLoader,
|
||||
} = await import("@medusajs/framework")
|
||||
/**
|
||||
* Initiates the database connection
|
||||
*/
|
||||
export async function initDb() {
|
||||
const { pgConnectionLoader, featureFlagsLoader } = await import(
|
||||
"@medusajs/framework"
|
||||
)
|
||||
|
||||
const pgConnection = pgConnectionLoader()
|
||||
await featureFlagsLoader()
|
||||
|
||||
container.register({
|
||||
[ContainerRegistrationKeys.LOGGER]: asValue(logger),
|
||||
})
|
||||
return pgConnection
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrates the database
|
||||
*/
|
||||
export async function migrateDatabase(appLoader: MedusaAppLoader) {
|
||||
try {
|
||||
const medusaAppLoader = new MedusaAppLoader()
|
||||
await medusaAppLoader.runModulesMigrations()
|
||||
const planner = await medusaAppLoader.getLinksExecutionPlanner()
|
||||
|
||||
const actionPlan = await planner.createPlan()
|
||||
await planner.executePlan(actionPlan)
|
||||
|
||||
/**
|
||||
* cleanup temporary created resources for the migrations
|
||||
* @internal I didnt find a god place to put that, should we eventually add a close function
|
||||
* to the planner to handle that part? so that you would do planner.close() and it will handle the cleanup
|
||||
* automatically just like we usually do for the classic migrations actions
|
||||
*/
|
||||
const { MedusaModule } = require("@medusajs/modules-sdk")
|
||||
MedusaModule.clearInstances()
|
||||
await appLoader.runModulesMigrations()
|
||||
} catch (err) {
|
||||
console.error("Something went wrong while running the migrations")
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
return pgConnection
|
||||
/**
|
||||
* Syncs links with the databse
|
||||
*/
|
||||
export async function syncLinks(appLoader: MedusaAppLoader) {
|
||||
try {
|
||||
const planner = await appLoader.getLinksExecutionPlanner()
|
||||
const actionPlan = await planner.createPlan()
|
||||
actionPlan.forEach((action) => {
|
||||
console.log(`Sync links: "${action.action}" ${action.tableName}`)
|
||||
})
|
||||
await planner.executePlan(actionPlan)
|
||||
} catch (err) {
|
||||
console.error("Something went wrong while syncing links")
|
||||
throw err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { asValue } from "awilix"
|
||||
import { ContainerRegistrationKeys, isObject } from "@medusajs/utils"
|
||||
|
||||
export function applyEnvVarsToProcess(env?: Record<any, any>) {
|
||||
if (isObject(env)) {
|
||||
Object.entries(env).forEach(([k, v]) => (process.env[k] = v))
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,20 @@
|
||||
import { asValue } from "awilix"
|
||||
import { ContainerLike, MedusaContainer } from "@medusajs/types"
|
||||
import { createMedusaContainer } from "@medusajs/utils"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
createMedusaContainer,
|
||||
} from "@medusajs/utils"
|
||||
import { createDatabase, dropDatabase } from "pg-god"
|
||||
import { getDatabaseURL } from "./database"
|
||||
import { startApp } from "./medusa-test-runner-utils/bootstrap-app"
|
||||
import { initDb } from "./medusa-test-runner-utils/use-db"
|
||||
import {
|
||||
initDb,
|
||||
migrateDatabase,
|
||||
syncLinks,
|
||||
} from "./medusa-test-runner-utils/use-db"
|
||||
import { configLoaderOverride } from "./medusa-test-runner-utils/config"
|
||||
import { applyEnvVarsToProcess } from "./medusa-test-runner-utils/utils"
|
||||
import { clearInstances } from "./medusa-test-runner-utils/clear-instances"
|
||||
|
||||
const axios = require("axios").default
|
||||
|
||||
@@ -80,6 +90,7 @@ export function medusaIntegrationTestRunner({
|
||||
schema = "public",
|
||||
env = {},
|
||||
debug = false,
|
||||
inApp = false,
|
||||
testSuite,
|
||||
}: {
|
||||
moduleName?: string
|
||||
@@ -87,6 +98,7 @@ export function medusaIntegrationTestRunner({
|
||||
dbName?: string
|
||||
schema?: string
|
||||
debug?: boolean
|
||||
inApp?: boolean
|
||||
testSuite: <TService = unknown>(options: MedusaSuiteOptions<TService>) => void
|
||||
}) {
|
||||
const tempName = parseInt(process.env.JEST_WORKER_ID || "1")
|
||||
@@ -104,7 +116,7 @@ export function medusaIntegrationTestRunner({
|
||||
|
||||
let shutdown = async () => void 0
|
||||
const dbUtils = dbTestUtilFactory()
|
||||
let container: ContainerLike
|
||||
let globalContainer: ContainerLike
|
||||
let apiUtils: any
|
||||
|
||||
let options = {
|
||||
@@ -124,7 +136,7 @@ export function medusaIntegrationTestRunner({
|
||||
},
|
||||
}
|
||||
),
|
||||
getContainer: () => container,
|
||||
getContainer: () => globalContainer,
|
||||
dbConfig: {
|
||||
dbName,
|
||||
schema,
|
||||
@@ -137,34 +149,45 @@ export function medusaIntegrationTestRunner({
|
||||
|
||||
const beforeAll_ = async () => {
|
||||
await configLoaderOverride(cwd, dbConfig)
|
||||
applyEnvVarsToProcess(env)
|
||||
|
||||
console.log(`Creating database ${dbName}`)
|
||||
await dbUtils.create(dbName)
|
||||
const { logger, container, MedusaAppLoader } = await import(
|
||||
"@medusajs/framework"
|
||||
)
|
||||
const appLoader = new MedusaAppLoader()
|
||||
container.register({
|
||||
[ContainerRegistrationKeys.LOGGER]: asValue(logger),
|
||||
})
|
||||
|
||||
try {
|
||||
dbUtils.pgConnection_ = await initDb({
|
||||
env,
|
||||
})
|
||||
console.log(`Creating database ${dbName}`)
|
||||
await dbUtils.create(dbName)
|
||||
dbUtils.pgConnection_ = await initDb()
|
||||
} catch (error) {
|
||||
console.error("Error initializing database", error?.message)
|
||||
throw error
|
||||
}
|
||||
|
||||
let containerRes
|
||||
let serverShutdownRes
|
||||
let portRes
|
||||
console.log(`Migrating database with core migrations and links ${dbName}`)
|
||||
await migrateDatabase(appLoader)
|
||||
await syncLinks(appLoader)
|
||||
await clearInstances()
|
||||
|
||||
let containerRes: MedusaContainer = container
|
||||
let serverShutdownRes: () => any
|
||||
let portRes: number
|
||||
|
||||
try {
|
||||
const {
|
||||
shutdown = () => void 0,
|
||||
container,
|
||||
container: appContainer,
|
||||
port,
|
||||
} = await startApp({
|
||||
cwd,
|
||||
env,
|
||||
})
|
||||
|
||||
containerRes = container
|
||||
containerRes = appContainer
|
||||
serverShutdownRes = shutdown
|
||||
portRes = port
|
||||
} catch (error) {
|
||||
@@ -172,9 +195,19 @@ export function medusaIntegrationTestRunner({
|
||||
throw error
|
||||
}
|
||||
|
||||
/**
|
||||
* Run application migrations and sync links when inside
|
||||
* an application
|
||||
*/
|
||||
if (inApp) {
|
||||
console.log(`Migrating database with core migrations and links ${dbName}`)
|
||||
await migrateDatabase(appLoader)
|
||||
await syncLinks(appLoader)
|
||||
}
|
||||
|
||||
const cancelTokenSource = axios.CancelToken.source()
|
||||
|
||||
container = containerRes
|
||||
globalContainer = containerRes
|
||||
shutdown = async () => {
|
||||
await serverShutdownRes()
|
||||
cancelTokenSource.cancel("Request canceled by shutdown")
|
||||
|
||||
@@ -58,11 +58,11 @@ export class RedisDistributedTransactionStorage
|
||||
|
||||
async onApplicationPrepareShutdown() {
|
||||
// Close worker gracefully, i.e. wait for the current jobs to finish
|
||||
await this.worker.close()
|
||||
await this.worker?.close()
|
||||
}
|
||||
|
||||
async onApplicationShutdown() {
|
||||
await this.queue.close()
|
||||
await this.queue?.close()
|
||||
}
|
||||
|
||||
async onApplicationStart() {
|
||||
|
||||
Reference in New Issue
Block a user