From 28c40025815f7632b8839b8c3eae55bcea728a4d Mon Sep 17 00:00:00 2001 From: Jordan Pittman Date: Fri, 26 Aug 2022 12:30:15 -0400 Subject: [PATCH] wip --- src/cli.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/cli.js b/src/cli.js index 6a9b3ed75f22..e8beca6e68e6 100644 --- a/src/cli.js +++ b/src/cli.js @@ -891,6 +891,36 @@ async function build() { } }) + /** + * When rapidly saving files atomically a couple of situations can happen: + * - The file is missing since the external program has deleted it by the time we've gotten around to reading it from the earlier save. + * - The file is being written to by the external program by the time we're going to read it and is thus treated as busy because a lock is held. + * + * To work around this we retry reading the file a handful of times with a delay between each attempt + * + * @param {string} path + * @param {number} tries + * @returns {string} + * @throws {Error} If the file is still missing or busy after the specified number of tries + */ + async function readFileWithRetries(path, tries = 5) { + for (let n = 0; n < tries; n++) { + try { + return await fs.promises.readFile(path, 'utf8') + } catch (err) { + if (n < tries) { + if (err.code === 'ENOENT' || err.code === 'EBUSY') { + await new Promise((resolve) => setTimeout(resolve, 10)) + + continue + } + } + + throw err + } + } + } + // Restore watching any files that are "removed" // This can happen when a file is pseudo-atomically replaced (a copy is created, overwritten, the old one is unlinked, and the new one is renamed) // TODO: An an optimization we should allow removal when the config changes