Skip to content

Commit

Permalink
fix: cache creation issues
Browse files Browse the repository at this point in the history
  • Loading branch information
matstyler committed Dec 5, 2024
1 parent dddfbb0 commit 87afe50
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 51 deletions.
7 changes: 2 additions & 5 deletions packages/cache/src/createCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,12 @@ export async function createCache(
) {
const setupFunctions = await getUniqueWalletSetupFunctions(walletSetupDirPath)

const cacheCreationPromises = await triggerCacheCreation(setupFunctions, hashes, downloadExtension, force)
const cacheCreationOutput = await triggerCacheCreation(setupFunctions, hashes, downloadExtension, force)

if (cacheCreationPromises.length === 0) {
if (cacheCreationOutput.length === 0) {
console.log('No new setup functions to cache. Exiting...')
return
}

// TODO: This line has no unit test. Not sure how to do it. Look into it later.
await Promise.all(cacheCreationPromises)

console.log('All wallet setup functions are now cached!')
}
5 changes: 3 additions & 2 deletions packages/cache/src/utils/extractWalletSetupFunction.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
export function extractWalletSetupFunction(sourceCode: string): string {
const match = sourceCode.match(/defineWalletSetup\s*\([^,]*,\s*(async\s*\([^)]*\)\s*=>\s*{[\s\S]*?})\s*\)/)
const match = sourceCode.match(
/defineWalletSetup\s*\([^,]*,\s*(async\s*\([^)]*\)\s*=>\s*{(?:[^{}]*|{(?:[^{}]*|{[^{}]*})*})*})\s*\)/

Check failure

Code scanning / CodeQL

Inefficient regular expression High

This part of the regular expression may cause exponential backtracking on strings starting with 'defineWalletSetup(,async()=>{' and containing many repetitions of 'z'.

Check failure

Code scanning / CodeQL

Inefficient regular expression High

This part of the regular expression may cause exponential backtracking on strings starting with 'defineWalletSetup(,async()=>{{' and containing many repetitions of 'z'.
)

if (!match || !match[1]) {
console.log('Failed to extract defineWalletSetup callback from:', sourceCode)
throw new Error('Could not find defineWalletSetup callback')
}

// Return just the callback function (second parameter)
return match[1]
}
52 changes: 27 additions & 25 deletions packages/cache/src/utils/triggerCacheCreation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,37 @@ export async function triggerCacheCreation(
const cacheDirPath = ensureCacheDirExists()
const extensionPath = await downloadExtension()

return Array.from(setupFunctions).map(async ([_, { fileName, setupFunction }], index) => {
if (!hashes[index]) {
throw new Error(`No hash found for ${fileName}`)
}
return await Promise.all(
Array.from(setupFunctions).map(async ([_, { fileName, setupFunction }], index) => {
if (!hashes[index]) {
throw new Error(`No hash found for ${fileName}`)
}

const funcHash = hashes[index]
const funcHash = hashes[index]

const cachePath = path.join(cacheDirPath, funcHash || 'unknown')
const doesCacheDirExist = await fs.exists(cachePath)
const isCacheDirEmpty = await isDirEmpty(cachePath)
const cachePath = path.join(cacheDirPath, funcHash || 'unknown')
const doesCacheDirExist = await fs.exists(cachePath)
const isCacheDirEmpty = await isDirEmpty(cachePath)

if (doesCacheDirExist) {
if (isCacheDirEmpty) {
// In case of incorrect Playwright setup, the cache dir will be empty. For now, we're just deleting it.
await fs.remove(cachePath)
} else {
if (!force) {
console.log(`Cache already exists for ${funcHash}. Skipping...`)
return
}
if (doesCacheDirExist) {
if (isCacheDirEmpty) {
// In case of incorrect Playwright setup, the cache dir will be empty. For now, we're just deleting it.
await fs.remove(cachePath)
} else {
if (!force) {
console.log(`Cache already exists for ${funcHash}. Skipping...`)
return
}

console.log(`Cache already exists for ${funcHash} but force flag is set. Deleting cache...`)
await fs.remove(cachePath)
console.log(`Cache already exists for ${funcHash} but force flag is set. Deleting cache...`)
await fs.remove(cachePath)
}
}
}

const fileNameWithCorrectExtension = fileName.replace(/\.(ts|js|mjs)$/, '.{ts,js,mjs}')
console.log(`Triggering cache creation for: ${funcHash} (${fileNameWithCorrectExtension})`)
// We're not inferring the return type here to make sure we don't accidentally await the function.
return createCacheForWalletSetupFunction(extensionPath, cachePath, setupFunction, fileNameWithCorrectExtension)
})
const fileNameWithCorrectExtension = fileName.replace(/\.(ts|js|mjs)$/, '.{ts,js,mjs}')
console.log(`Triggering cache creation for: ${funcHash} (${fileNameWithCorrectExtension})`)
// We're not inferring the return type here to make sure we don't accidentally await the function.
return createCacheForWalletSetupFunction(extensionPath, cachePath, setupFunction, fileNameWithCorrectExtension)
})
)
}
39 changes: 20 additions & 19 deletions packages/cache/test/utils/triggerCacheCreation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,15 @@ describe('triggerCacheCreation', () => {
expect(downloadExtension).toHaveBeenCalledOnce()
})

it.skip('calls createCacheForWalletSetupFunction with correct arguments', async () => {
it('calls createCacheForWalletSetupFunction with correct arguments', async () => {
await triggerCacheCreation(setupFunctions, hashes, downloadExtension, false)

expect(createCacheForWalletSetupFunctionSpy).toHaveBeenCalledTimes(2)
expectCreateCacheForWalletSetupFunction(1, setupFunctions, 'hash1')
expectCreateCacheForWalletSetupFunction(2, setupFunctions, 'hash2')
})

it.skip('checks if cache already exists for each entry', async () => {
it('checks if cache already exists for each entry', async () => {
const existsSpy = vi.spyOn(fsExtra, 'exists')
await triggerCacheCreation(setupFunctions, hashes, downloadExtension, false)

Expand All @@ -134,35 +134,36 @@ describe('triggerCacheCreation', () => {
expect(existsSpy).toHaveBeenNthCalledWith(2, path.join(ROOT_DIR, 'hash2'))
})

it('returns an array of createCacheForWalletSetupFunction promises', async () => {
const promises = await triggerCacheCreation(setupFunctions, hashes, downloadExtension, false)
it('returns an array of createCacheForWalletSetupFunction feedback', async () => {
const output = await triggerCacheCreation(setupFunctions, hashes, downloadExtension, false)

console.log(promises)

expect(promises).toHaveLength(2)
expect(promises[0]).toBeInstanceOf(Promise)
expect(promises[1]).toBeInstanceOf(Promise)
expect(output).toHaveLength(2)
expect(output[0]).toBe('Resolved Quack! 🦆')
expect(output[1]).toBe('Resolved Quack! 🦆')
})

describe('when force flag is false', () => {
it.skip('ignores setup function for which cache already exists', async () => {
it('ignores setup function for which cache already exists', async () => {
const setupFunctions = prepareSetupFunctions(['hash1', 'hash2', 'hash3'])

// Creating cache for 2nd setup function.
fs.mkdirSync(path.join(ROOT_DIR, 'hash2'))

const promises = await triggerCacheCreation(setupFunctions, [...hashes, 'hash3'], downloadExtension, false)
const output = await triggerCacheCreation(setupFunctions, [...hashes, 'hash3'], downloadExtension, false)

// @ts-ignore
const filterGeneratedCacheOutput = (output) => output === 'Resolved Quack! 🦆'

expect(promises).toHaveLength(2)
expect(output.filter(filterGeneratedCacheOutput)).toHaveLength(2)
expect(createCacheForWalletSetupFunctionSpy).toHaveBeenCalledTimes(2)
expectCreateCacheForWalletSetupFunction(1, setupFunctions, 'hash1')
expectCreateCacheForWalletSetupFunction(2, setupFunctions, 'hash3')
})
})

describe('when force flag is true', () => {
it.skip('removes cache if it already exists for given setup function', async () => {
const setupFunctions = prepareSetupFunctions(['hash1', 'hash2', 'hash3'])
it('removes cache if it already exists for given setup function', async () => {
const setupFunctions = prepareSetupFunctions([...hashes, 'hash3'])

// Creating cache for 2nd setup function.
const pathToExistingCache = path.join(ROOT_DIR, 'hash2')
Expand All @@ -173,19 +174,19 @@ describe('triggerCacheCreation', () => {
expect(fs.existsSync(pathToExistingCache)).toBe(false)
})

it.skip('calls createCacheForWalletSetupFunction for setup functions that were previously cached', async () => {
it('calls createCacheForWalletSetupFunction for setup functions that were previously cached', async () => {
const setupFunctions = prepareSetupFunctions([...hashes, 'hash3'])

// Creating cache for 2nd setup function.
fs.mkdirSync(path.join(ROOT_DIR, 'hash2'))

const promises = await triggerCacheCreation(setupFunctions, [...hashes, 'hash3'], downloadExtension, true)
const output = await triggerCacheCreation(setupFunctions, [...hashes, 'hash3'], downloadExtension, true)

expect(promises).toHaveLength(3)
expect(output).toHaveLength(3)
expect(createCacheForWalletSetupFunctionSpy).toHaveBeenCalledTimes(3)
expectCreateCacheForWalletSetupFunction(1, setupFunctions, 'hash1')
expectCreateCacheForWalletSetupFunction(2, setupFunctions, 'hash2')
expectCreateCacheForWalletSetupFunction(3, setupFunctions, 'hash3')
expectCreateCacheForWalletSetupFunction(2, setupFunctions, 'hash3')
expectCreateCacheForWalletSetupFunction(3, setupFunctions, 'hash2')
})
})
})

0 comments on commit 87afe50

Please sign in to comment.