Skip to content

Commit

Permalink
Merge pull request #9 from rainlanguage/2024-05-04-memoizer
Browse files Browse the repository at this point in the history
memoizer
  • Loading branch information
thedavidmeister authored May 6, 2024
2 parents 5858c6a + f385170 commit 95316ac
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 0 deletions.
1 change: 1 addition & 0 deletions packages/sushi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,7 @@
"date-fns": "3.3.1",
"decimal.js-light": "2.5.1",
"lodash.flatmap": "4.5.0",
"memoize-fs": "github:rouzwelt/memoize-fs#e5fcc9f6effc4ad087514372a53a49d380520ad5",
"numbro": "2.5.0",
"seedrandom": "3.0.5",
"serialijse": "0.3.0",
Expand Down
53 changes: 53 additions & 0 deletions packages/sushi/src/router/memoizer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import fs from 'fs'
import { describe, expect, it } from 'vitest'
import { memoizer } from './memoizer.js'

describe('Memoizer', async () => {
it('should serialize, memoize, read from cache, deserialize', async () => {
let didHitCacheOnce = false
const testFn = (value1: any) => {
didHitCacheOnce = !didHitCacheOnce
return {
...value1,
someOtherValue: 'some data',
}
}
const testMemoizer = await memoizer.fn(testFn)

const testValue = {
bigint: 12345n,
string: 'some text',
number: 123,
bool: true,
obj: {
prop: 'some prop',
},
}
const noCacheHitReturnedValue = await testMemoizer(testValue)
const cacheHitReturnedValue = await testMemoizer(testValue)
const expectedReturnedValue = {
bigint: 12345n,
string: 'some text',
number: 123,
bool: true,
obj: {
prop: 'some prop',
},
someOtherValue: 'some data',
}

expect(didHitCacheOnce).toEqual(true)
expect(noCacheHitReturnedValue).toStrictEqual(expectedReturnedValue)
expect(cacheHitReturnedValue).toStrictEqual(expectedReturnedValue)

// read cached file content
const cacheFileContent = fs.readFileSync(
`./mem-cache/${fs.readdirSync('./mem-cache')[0]}`,
{ encoding: 'utf-8' },
)
const expectedCachedContent =
'{"data":{"bigint":"12345n","string":"some text","number":123,"bool":true,"obj":{"prop":"some prop"},"someOtherValue":"some data"}}'

expect(cacheFileContent).toEqual(expectedCachedContent)
})
})
34 changes: 34 additions & 0 deletions packages/sushi/src/router/memoizer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import memoize from 'memoize-fs'

const serialize = (val: any) => {
const circRefColl: any[] = []
return JSON.stringify(val, (_name, value) => {
if (typeof value === 'function') {
return // ignore arguments and attributes of type function silently
}
if (typeof value === 'object' && value !== null) {
if (circRefColl.indexOf(value) !== -1) {
// circular reference has been found, discard key
return
}
// store value in collection
circRefColl.push(value)
}
if (typeof value === 'bigint') return `${value.toString()}n`
return value
})
}

const deserialize = (val: string) => {
return JSON.parse(val, (_key, value) => {
if (typeof value === 'string' && /^\d+n$/.test(value)) {
return BigInt(value.slice(0, -1))
} else return value
}).data
}

export const memoizer = memoize({
cachePath: './mem-cache',
serialize,
deserialize,
})
20 changes: 20 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 95316ac

Please sign in to comment.