From 733ee097b524f465e2b51a6884e0a9c64adff9ca Mon Sep 17 00:00:00 2001 From: Sunil Surana Date: Sat, 27 Apr 2024 14:29:09 +0000 Subject: [PATCH] fix : Synchronize read and writes to avoid race condition reading transpiled files from disk cache First add a maker file to check if the previous write was fully completed. Then again in writefile section change the write mode to wx which uses exclusive lock and if two writes happen same time and we get EEXist error then ignore that FIX for #30577 --- .../src/transform/compilationCache.ts | 34 +++++++++++++------ 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/packages/playwright/src/transform/compilationCache.ts b/packages/playwright/src/transform/compilationCache.ts index 8c975af443ab3..b3c56edacd3ed 100644 --- a/packages/playwright/src/transform/compilationCache.ts +++ b/packages/playwright/src/transform/compilationCache.ts @@ -126,23 +126,35 @@ export function getFromCompilationCache(filename: string, hash: string, moduleUr const codePath = cachePath + '.js'; const sourceMapPath = cachePath + '.map'; const dataPath = cachePath + '.data'; - try { - const cachedCode = fs.readFileSync(codePath, 'utf8'); - const serializedCache = _innerAddToCompilationCacheAndSerialize(filename, { codePath, sourceMapPath, dataPath, moduleUrl }); - return { cachedCode, serializedCache }; - } catch { + const markerFile = codePath + '-marker'; + if (fs.existsSync(markerFile)) { + try { + const cachedCode = fs.readFileSync(codePath, 'utf8'); + const serializedCache = _innerAddToCompilationCacheAndSerialize(filename, { codePath, sourceMapPath, dataPath, moduleUrl }); + return { cachedCode, serializedCache }; + } catch { + } } return { addToCache: (code: string, map: any | undefined | null, data: Map) => { if (isWorkerProcess()) return {}; - fs.mkdirSync(path.dirname(cachePath), { recursive: true }); - if (map) - fs.writeFileSync(sourceMapPath, JSON.stringify(map), 'utf8'); - if (data.size) - fs.writeFileSync(dataPath, JSON.stringify(Object.fromEntries(data.entries()), undefined, 2), 'utf8'); - fs.writeFileSync(codePath, code, 'utf8'); + try { + fs.mkdirSync(path.dirname(cachePath), { recursive: true }); + if (map) + fs.writeFileSync(sourceMapPath, JSON.stringify(map), { encoding: 'utf8', flag: 'wx' }); + if (data.size) + fs.writeFileSync(dataPath, JSON.stringify(Object.fromEntries(data.entries()), undefined, 2), { encoding: 'utf8', flag: 'wx' }); + fs.writeFileSync(codePath, code, 'utf8'); + fs.closeSync(fs.openSync(markerFile, 'wx')); + } + catch (error) { + if (error.code === 'EEXIST') { + } else { + throw error; + } + } const serializedCache = _innerAddToCompilationCacheAndSerialize(filename, { codePath, sourceMapPath, dataPath, moduleUrl }); return { serializedCache }; }