fix(): Index integration tests flackyness (#13953)

* fix(): Index integration tests flackyness

* fix

* Create twenty-eels-remain.md

* fix

* fix

* fix

* fix

* finalize

* finalize

* finalize

* finalize

* finalize

* finalize

* chore: empty commit

* finalize

* finalize

* chore: empty commit

* finalize

* finalize
This commit is contained in:
Adrien de Peretti authored and GitHub committed 2025-11-05 10:40:12 +01:00
1 parent c6556d1256
commit 9d9d0397a8
14 files changed
+112 -89

No files matched your search

@@ -1,3 +1,5 @@
import { promiseAll } from "./promise-all"
/**
* Execute functions with a concurrency limit
* @param functions Array of functions to execute in parallel
@@ -7,13 +9,12 @@ export async function executeWithConcurrency<T>(
functions: (() => Promise<T>)[],
concurrency: number
): Promise<PromiseSettledResult<Awaited<T>>[]> {
const results: PromiseSettledResult<Awaited<T>>[] = new Array(
functions.length
)
const functionsLength = functions.length
const results: PromiseSettledResult<Awaited<T>>[] = new Array(functionsLength)
let currentIndex = 0
const executeNext = async (): Promise<void> => {
while (currentIndex < functions.length) {
while (currentIndex < functionsLength) {
const index = currentIndex++
const result = await Promise.allSettled([functions[index]()])
results[index] = result[0]
@@ -21,11 +22,11 @@ export async function executeWithConcurrency<T>(
}
const workers: Promise<void>[] = []
for (let i = 0; i < concurrency; i++) {
for (let i = 0; i < Math.min(concurrency, functionsLength); i++) {
workers.push(executeNext())
}
await Promise.all(workers)
await promiseAll(workers)
return results
}
+1 -1
View File
@@ -32,7 +32,7 @@
"axios": "^1.13.1",
"express": "^4.21.0",
"get-port": "^5.1.1",
"randomatic": "^3.1.1"
"ulid": "^2.3.0"
},
"peerDependencies": {
"@medusajs/framework": "2.11.2",
+50 -7
View File
@@ -237,6 +237,8 @@ export const dbTestUtilFactory = (): any => ({
let hasIndexTables = false
const tablesToTruncate: string[] = []
const allTablesToVerify: string[] = []
for (const { table_name } of tableNames) {
if (mainPartitionTables.includes(table_name)) {
hasIndexTables = true
@@ -246,20 +248,61 @@ export const dbTestUtilFactory = (): any => ({
table_name.startsWith(skipIndexPartitionPrefix) ||
mainPartitionTables.includes(table_name)
) {
allTablesToVerify.push(table_name)
continue
}
tablesToTruncate.push(`${schema}."${table_name}"`)
}
if (tablesToTruncate.length > 0) {
await runRawQuery(`TRUNCATE ${tablesToTruncate.join(", ")};`)
allTablesToVerify.push(table_name)
}
if (hasIndexTables) {
await runRawQuery(
`TRUNCATE ${schema}.index_data, ${schema}.index_relation;`
)
const allTablesToTruncase = [
...tablesToTruncate,
...(hasIndexTables ? mainPartitionTables : []),
].join(", ")
if (allTablesToTruncase) {
await runRawQuery(`TRUNCATE ${allTablesToTruncase};`)
}
const verifyEmpty = async (maxRetries = 5) => {
for (let retry = 0; retry < maxRetries; retry++) {
const countQueries = allTablesToVerify.map(
(tableName) =>
`SELECT '${tableName}' as table_name, COUNT(*) as count FROM ${schema}."${tableName}"`
)
const { rows: counts } = await runRawQuery(
countQueries.join(" UNION ALL ")
)
const nonEmptyTables = counts.filter(
(row: { table_name: string; count: string }) =>
parseInt(row.count) > 0
)
if (nonEmptyTables.length === 0) {
return true
}
if (retry < maxRetries - 1) {
await new Promise((resolve) => setTimeout(resolve, 100))
} else {
const tableList = nonEmptyTables
.map(
(t: { table_name: string; count: string }) =>
`${t.table_name}(${t.count})`
)
.join(", ")
logger.warn(
`Some tables still contain data after truncate: ${tableList}`
)
}
}
return false
}
await verifyEmpty()
} catch (error) {
logger.error("Error during database teardown:", error)
throw error
-19
View File
@@ -1,19 +0,0 @@
import randomize from "randomatic"
class IdMap {
ids = {}
getId(key, prefix = "", length = 10) {
if (this.ids[key]) {
return this.ids[key]
}
const id = `${prefix && prefix + "_"}${randomize("Aa0", length)}`
this.ids[key] = id
return id
}
}
const instance = new IdMap()
export default instance
-1
View File
@@ -1,6 +1,5 @@
export * as TestDatabaseUtils from "./database"
export * as TestEventUtils from "./events"
export { default as IdMap } from "./id-map"
export * from "./init-modules"
export * as JestUtils from "./jest"
export * from "./medusa-test-runner"
@@ -20,6 +20,7 @@ import {
syncLinks,
} from "./medusa-test-runner-utils"
import { waitWorkflowExecutions } from "./medusa-test-runner-utils/wait-workflow-executions"
import { ulid } from "ulid"
export interface MedusaSuiteOptions {
dbConnection: any // knex instance
@@ -84,8 +85,7 @@ class MedusaTestRunner {
constructor(config: TestRunnerConfig) {
const tempName = parseInt(process.env.JEST_WORKER_ID || "1")
const moduleName =
config.moduleName ?? Math.random().toString(36).substring(7)
const moduleName = config.moduleName ?? ulid()
this.dbName =
config.dbName ??
`medusa-${moduleName.toLowerCase()}-integration-${tempName}`
@@ -13,6 +13,7 @@ import * as fs from "fs"
import { getDatabaseURL, getMikroOrmWrapper, TestDatabase } from "./database"
import { initModules, InitModulesOptions } from "./init-modules"
import { default as MockEventBusService } from "./mock-event-bus-service"
import { ulid } from "ulid"
export interface SuiteOptions<TService = unknown> {
MikroOrmWrapper: TestDatabase
@@ -114,9 +115,10 @@ class ModuleTestRunner<TService = any> {
constructor(config: ModuleTestRunnerConfig<TService>) {
const tempName = parseInt(process.env.JEST_WORKER_ID || "1")
this.moduleName = config.moduleName
const moduleName = this.moduleName ?? ulid()
this.dbName =
config.dbName ??
`medusa-${config.moduleName.toLowerCase()}-integration-${tempName}`
`medusa-${moduleName.toLowerCase()}-integration-${tempName}`
this.schema = config.schema ?? "public"
this.debug = config.debug ?? false
this.resolve = config.resolve
@@ -29,7 +29,7 @@
"resolve:aliases": "yarn run -T tsc --showConfig -p tsconfig.json > tsconfig.resolved.json && yarn run -T tsc-alias -p tsconfig.resolved.json && yarn run -T rimraf tsconfig.resolved.json",
"build": "yarn run -T rimraf dist && yarn run -T tsc --build && npm run resolve:aliases",
"test": "../../../node_modules/.bin/jest --passWithNoTests --bail --forceExit --testPathPattern=src",
"test:integration": "../../../node_modules/.bin/jest --passWithNoTests --forceExit --testPathPattern=\"integration-tests/__tests__/.*\\.spec\\.ts\"",
"test:integration": "../../../node_modules/.bin/jest --passWithNoTests --forceExit --testPathPattern=\"integration-tests/__tests__/index\\.spec\\.ts\" && ../../../node_modules/.bin/jest --passWithNoTests --forceExit --testPathPattern=\"integration-tests/__tests__/race\\.spec\\.ts\" && ../../../node_modules/.bin/jest --passWithNoTests --forceExit --testPathPattern=\"integration-tests/__tests__/subscribe\\.spec\\.ts\"",
"migration:initial": "MIKRO_ORM_CLI_CONFIG=./mikro-orm.config.dev.ts MIKRO_ORM_ALLOW_GLOBAL_CLI=true medusa-mikro-orm migration:create --initial",
"migration:create": "MIKRO_ORM_CLI_CONFIG=./mikro-orm.config.dev.ts MIKRO_ORM_ALLOW_GLOBAL_CLI=true medusa-mikro-orm migration:create",
"migration:up": "MIKRO_ORM_CLI_CONFIG=./mikro-orm.config.dev.ts MIKRO_ORM_ALLOW_GLOBAL_CLI=true medusa-mikro-orm migration:up",