Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memoizer #9

Merged
merged 1 commit into from
May 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.

Loading