Lock starting containers.

This commit is contained in:
Sam Rose 2024-06-11 14:39:44 +01:00
parent 115737c46c
commit 1d1ca694c8
No known key found for this signature in database
2 changed files with 42 additions and 13 deletions

2
.gitignore vendored
View File

@ -8,6 +8,8 @@ bb-airgapped.tar.gz
packages/server/build/oldClientVersions/**/*
packages/builder/src/components/deploy/clientVersions.json
packages/server/src/integrations/tests/utils/*.lock
# Logs
logs
*.log

View File

@ -6,6 +6,9 @@ import * as mssql from "./mssql"
import * as mariadb from "./mariadb"
import { GenericContainer } from "testcontainers"
import { testContainerUtils } from "@budibase/backend-core/tests"
import lockfile from "proper-lockfile"
import path from "path"
import fs from "fs"
export type DatasourceProvider = () => Promise<Datasource>
@ -67,6 +70,27 @@ export async function rawQuery(ds: Datasource, sql: string): Promise<any> {
export async function startContainer(container: GenericContainer) {
container = container.withReuse().withLabels({ "com.budibase": "true" })
// If two tests try to spin up the same container at the same time, there's a
// possibility that two containers of the same type will be started. To avoid
// this, we use a filesystem lock to ensure that only one container of a given
// type is started at a time.
const imageName = (container as any).imageName.string as string
const lockPath = path.resolve(
__dirname,
`${imageName.replaceAll("/", "-")}.lock`
)
// The `proper-lockfile` library needs the file we're locking on to exist
// before it can lock it.
if (!fs.existsSync(lockPath)) {
fs.writeFileSync(lockPath, "")
}
await lockfile.lock(lockPath, {
retries: 10,
})
try {
const startedContainer = await container.start()
const info = testContainerUtils.getContainerById(startedContainer.getId())
@ -83,4 +107,7 @@ export async function startContainer(container: GenericContainer) {
// that reason, we don't use testcontainers' `getExposedPort` function,
// preferring instead our own method that guaranteed v4 ports.
return testContainerUtils.getExposedV4Ports(info)
} finally {
await lockfile.unlock(lockPath)
}
}