From f990e082b0713db46c92d2ed8f70bdfb24c100f1 Mon Sep 17 00:00:00 2001 From: Michal Piechowiak Date: Thu, 11 Aug 2022 10:40:01 +0200 Subject: [PATCH] fix(test): clear and close lmdb after each test suite (#36343) --- jest.config.js | 1 + jest.environment.ts | 23 ++++++++++ .../gatsby/src/utils/__tests__/cache-lmdb.ts | 11 ++--- packages/gatsby/src/utils/cache-lmdb.ts | 46 ++++++++++++++----- 4 files changed, 64 insertions(+), 17 deletions(-) create mode 100644 jest.environment.ts diff --git a/jest.config.js b/jest.config.js index 9f70047f284e7..7ba7a6d544631 100644 --- a/jest.config.js +++ b/jest.config.js @@ -149,4 +149,5 @@ module.exports = { moduleFileExtensions: [`js`, `jsx`, `ts`, `tsx`, `json`], setupFiles: [`/.jestSetup.js`], setupFilesAfterEnv: [`jest-extended`], + testEnvironment: `/jest.environment.ts`, } diff --git a/jest.environment.ts b/jest.environment.ts new file mode 100644 index 0000000000000..3746371ccf091 --- /dev/null +++ b/jest.environment.ts @@ -0,0 +1,23 @@ +const NodeEnvironment = require(`jest-environment-node`) + +class CustomEnvironment extends NodeEnvironment { + constructor(config, context) { + super(config, context) + } + + async teardown(): Promise { + // close open lmdbs after running test suite + // this prevent dangling open handles that sometimes cause problems + // particularly in windows tests (failures to move or delete a db file) + if (this.global.__GATSBY_OPEN_ROOT_LMDBS) { + for (const rootDb of this.global.__GATSBY_OPEN_ROOT_LMDBS.values()) { + await rootDb.clearAsync() + await rootDb.close() + } + this.global.__GATSBY_OPEN_ROOT_LMDBS = undefined + } + await super.teardown() + } +} + +module.exports = CustomEnvironment diff --git a/packages/gatsby/src/utils/__tests__/cache-lmdb.ts b/packages/gatsby/src/utils/__tests__/cache-lmdb.ts index 0fc342121f057..9a45c3dc66303 100644 --- a/packages/gatsby/src/utils/__tests__/cache-lmdb.ts +++ b/packages/gatsby/src/utils/__tests__/cache-lmdb.ts @@ -12,13 +12,12 @@ describeWhenLMDB(`cache-lmdb`, () => { let cache beforeAll(async () => { - const { default: GatsbyCacheLmdb } = await import(`../cache-lmdb`) - cache = new GatsbyCacheLmdb({ name: `__test__` }).init() - const fileDir = path.join( - process.cwd(), - `.cache/caches-lmdb-${process.env.JEST_WORKER_ID}` + const { default: GatsbyCacheLmdb, resetCache } = await import( + `../cache-lmdb` ) - await fs.emptyDir(fileDir) + + await resetCache() + cache = new GatsbyCacheLmdb({ name: `__test__` }).init() }) it(`it can be instantiated`, () => { diff --git a/packages/gatsby/src/utils/cache-lmdb.ts b/packages/gatsby/src/utils/cache-lmdb.ts index 98e94f45c1dc3..addac1cbc40b6 100644 --- a/packages/gatsby/src/utils/cache-lmdb.ts +++ b/packages/gatsby/src/utils/cache-lmdb.ts @@ -1,6 +1,6 @@ import { open, RootDatabase, Database, DatabaseOptions } from "lmdb" -import fs from "fs-extra" -import path from "path" +import * as fs from "fs-extra" +import * as path from "path" // Since the regular GatsbyCache saves to "caches" this should be "caches-lmdb" const cacheDbFile = @@ -13,8 +13,16 @@ const cacheDbFile = }` : `caches-lmdb` +const dbPath = path.join(process.cwd(), `.cache/${cacheDbFile}`) + +function getAlreadyOpenedStore(): RootDatabase | undefined { + if (!globalThis.__GATSBY_OPEN_ROOT_LMDBS) { + globalThis.__GATSBY_OPEN_ROOT_LMDBS = new Map() + } + return globalThis.__GATSBY_OPEN_ROOT_LMDBS.get(dbPath) +} + export default class GatsbyCacheLmdb { - private static store private db: Database | undefined private encoding: DatabaseOptions["encoding"] public readonly name: string @@ -44,15 +52,21 @@ export default class GatsbyCacheLmdb { } private static getStore(): RootDatabase { - if (!GatsbyCacheLmdb.store) { - GatsbyCacheLmdb.store = open({ - name: `root`, - path: path.join(process.cwd(), `.cache/${cacheDbFile}`), - compression: true, - maxDbs: 200, - }) + let rootDb = getAlreadyOpenedStore() + if (rootDb) { + return rootDb } - return GatsbyCacheLmdb.store + + rootDb = open({ + name: `root`, + path: dbPath, + compression: true, + maxDbs: 200, + }) + + globalThis.__GATSBY_OPEN_ROOT_LMDBS.set(dbPath, rootDb) + + return rootDb } private getDb(): Database { @@ -78,3 +92,13 @@ export default class GatsbyCacheLmdb { return this.getDb().remove(key) as unknown as Promise } } + +export async function resetCache(): Promise { + const store = getAlreadyOpenedStore() + if (store) { + await store.close() + globalThis.__GATSBY_OPEN_ROOT_LMDBS.delete(dbPath) + } + + await fs.emptyDir(dbPath) +}