Skip to content

Commit

Permalink
feat(gatsby): Add cache-lmdb implementation (#32373)
Browse files Browse the repository at this point in the history
  • Loading branch information
LekoArts committed Jul 15, 2021
1 parent 15b49b6 commit 7897834
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 1 deletion.
47 changes: 47 additions & 0 deletions packages/gatsby/src/utils/__tests__/cache-lmdb.ts
@@ -0,0 +1,47 @@
import * as path from "path"
import fs from "fs-extra"
import { describeWhenLMDB } from "../worker/__tests__/test-helpers"

const complexObject = {
key: `value`,
another_key: 2,
nested: { hello: `world`, foo: `bar`, nested: { super: `duper` } },
}

describeWhenLMDB(`cache-lmdb`, () => {
let cache

beforeAll(async () => {
const { default: GatsbyCacheLmdb } = await import(`../cache-lmdb`)
cache = new GatsbyCacheLmdb({ name: `__test__` })
const fileDir = path.join(
process.cwd(),
`.cache/caches-lmdb-${process.env.JEST_WORKER_ID}`
)
await fs.emptyDir(fileDir)
})

it(`it can be instantiated`, () => {
if (!cache) fail(`cache not instantiated`)
})
it(`returns cache instance with get/set methods`, () => {
expect(cache.get).toEqual(expect.any(Function))
expect(cache.set).toEqual(expect.any(Function))
})
describe(`set`, () => {
it(`resolves to the value it cached (string)`, () =>
expect(cache.set(`string`, `I'm a simple string`)).resolves.toBe(
`I'm a simple string`
))
it(`resolves to the value it cached (object)`, () =>
expect(cache.set(`object`, complexObject)).resolves.toStrictEqual(
complexObject
))
})
describe(`get`, () => {
it(`resolves to the found value (string)`, () =>
expect(cache.get(`string`)).resolves.toBe(`I'm a simple string`))
it(`resolves to the found value (object)`, () =>
expect(cache.get(`object`)).resolves.toStrictEqual(complexObject))
})
})
53 changes: 53 additions & 0 deletions packages/gatsby/src/utils/cache-lmdb.ts
@@ -0,0 +1,53 @@
import { open, RootDatabase, Database } from "lmdb-store"
import path from "path"

// Since the regular GatsbyCache saves to "caches" this should be "caches-lmdb"
const cacheDbFile =
process.env.NODE_ENV === `test`
? `caches-lmdb-${
// FORCE_TEST_DATABASE_ID will be set if this gets executed in worker context
// when running jest tests. JEST_WORKER_ID will be set when this gets executed directly
// in test context (jest will use jest-worker internally).
process.env.FORCE_TEST_DATABASE_ID ?? process.env.JEST_WORKER_ID
}`
: `caches-lmdb`

export default class GatsbyCacheLmdb {
private static store
private db: Database | undefined
public readonly name: string

constructor({ name = `db` }: { name: string }) {
this.name = name
}

private static getStore(): RootDatabase {
if (!GatsbyCacheLmdb.store) {
GatsbyCacheLmdb.store = open({
name: `root`,
path: path.join(process.cwd(), `.cache/${cacheDbFile}`),
compression: true,
maxDbs: 200,
})
}
return GatsbyCacheLmdb.store
}

private getDb(): Database {
if (!this.db) {
this.db = GatsbyCacheLmdb.getStore().openDB({
name: this.name,
})
}
return this.db
}

async get<T = unknown>(key): Promise<T | undefined> {
return this.getDb().get(key)
}

async set<T>(key: string, value: T): Promise<T | undefined> {
await this.getDb().put(key, value)
return value
}
}
8 changes: 7 additions & 1 deletion packages/gatsby/src/utils/get-cache.ts
@@ -1,11 +1,17 @@
import GatsbyCache from "./cache"
import { isLmdbStore } from "../datastore"

const caches = new Map<string, GatsbyCache>()

export const getCache = (name: string): GatsbyCache => {
let cache = caches.get(name)
if (!cache) {
cache = new GatsbyCache({ name }).init()
if (isLmdbStore()) {
const GatsbyCacheLmdb = require(`./cache-lmdb`).default
cache = new GatsbyCacheLmdb({ name }) as GatsbyCache
} else {
cache = new GatsbyCache({ name }).init()
}
caches.set(name, cache)
}
return cache
Expand Down

0 comments on commit 7897834

Please sign in to comment.