1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

Add error resiliency to waitForPath

Signed-off-by: Sebastian Malton <sebastian@malton.name>
This commit is contained in:
Sebastian Malton 2022-01-27 16:12:28 -05:00
parent 45907e8a2c
commit bc24aaa5ac
2 changed files with 67 additions and 30 deletions

View File

@ -3,30 +3,53 @@
* Licensed under MIT License. See LICENSE in root directory for more information. * Licensed under MIT License. See LICENSE in root directory for more information.
*/ */
import { watch } from "chokidar"; import { FSWatcher } from "chokidar";
import path from "path"; import path from "path";
/** /**
* Wait for `filePath` and all parent directories to exist. * Wait for `filePath` and all parent directories to exist.
* @param filePath The file path to wait until it exists * @param pathname The file path to wait until it exists
*
* NOTE: There is technically a race condition in this function of the form
* "time-of-check to time-of-use" because we have to wait for each parent
* directory to exist first.
*/ */
export async function waitForPath(filePath: string): Promise<void> { export async function waitForPath(pathname: string): Promise<void> {
const dirOfPath = path.dirname(filePath); const dirOfPath = path.dirname(pathname);
if (dirOfPath === filePath) { if (dirOfPath === pathname) {
// The root of this filesystem, assume it exists // The root of this filesystem, assume it exists
return; return;
} else { } else {
await waitForPath(dirOfPath); await waitForPath(dirOfPath);
} }
return new Promise(resolve => { return new Promise((resolve, reject) => {
watch(dirOfPath, { const watcher = new FSWatcher({
depth: 0, depth: 0,
}).on("all", (event, path) => { disableGlobbing: true,
if ((event === "add" || event === "addDir") && path === filePath) {
resolve();
}
}); });
const onAddOrAddDir = (filePath: string) => {
if (filePath === pathname) {
watcher.unwatch(dirOfPath);
watcher
.close()
.then(() => resolve())
.catch(reject);
}
};
const onError = (error: any) => {
watcher.unwatch(dirOfPath);
watcher
.close()
.then(() => reject(error))
.catch(() => reject(error));
};
watcher
.on("add", onAddOrAddDir)
.on("addDir", onAddOrAddDir)
.on("error", onError)
.add(dirOfPath);
}); });
} }

View File

@ -6,7 +6,7 @@ import { getInjectable, lifecycleEnum } from "@ogre-tools/injectable";
import { computed, IComputedValue, observable } from "mobx"; import { computed, IComputedValue, observable } from "mobx";
import path from "path"; import path from "path";
import os from "os"; import os from "os";
import { getOrInsert, waitForPath } from "../../../utils"; import { delay, getOrInsert, waitForPath } from "../../../utils";
import { watch } from "chokidar"; import { watch } from "chokidar";
import { readFile } from "fs/promises"; import { readFile } from "fs/promises";
import logger from "../../../../common/logger"; import logger from "../../../../common/logger";
@ -58,24 +58,38 @@ function watchUserCreateResourceTemplates(): IComputedValue<RawTemplates[]> {
templates.delete(filePath); templates.delete(filePath);
}; };
waitForPath(userTemplatesFolder) (async () => {
.then(() => { for (let i = 1;; i *= 2) {
console.log("watching", userTemplatesFolder); try {
watch(userTemplatesFolder, { await waitForPath(userTemplatesFolder);
disableGlobbing: true, break;
ignorePermissionErrors: true, } catch (error) {
usePolling: false, logger.warn(`[USER-CREATE-RESOURCE-TEMPLATES]: encountered error while waiting for ${userTemplatesFolder} to exist, waiting and trying again`, error);
awaitWriteFinish: { await delay(i * 1000); // exponential backoff in seconds
pollInterval: 100, }
stabilityThreshold: 1000, }
},
ignoreInitial: false, /**
atomic: 150, // for "atomic writes" * NOTE: There is technically a race condition here of the form "time-of-check to time-of-use"
}) */
.on("add", onAddOrChange) watch(userTemplatesFolder, {
.on("change", onAddOrChange) disableGlobbing: true,
.on("unlink", onUnlink); ignorePermissionErrors: true,
}); usePolling: false,
awaitWriteFinish: {
pollInterval: 100,
stabilityThreshold: 1000,
},
ignoreInitial: false,
atomic: 150, // for "atomic writes"
})
.on("add", onAddOrChange)
.on("change", onAddOrChange)
.on("unlink", onUnlink)
.on("error", error => {
logger.warn(`[USER-CREATE-RESOURCE-TEMPLATES]: encountered error while watching files under ${userTemplatesFolder}`, error);
});
})();
return computed(() => groupTemplates(templates)); return computed(() => groupTemplates(templates));
} }