Skip to content

Commit

Permalink
Simplify exists cache, remove unnecessary normalization
Browse files Browse the repository at this point in the history
  • Loading branch information
zachleat committed Oct 18, 2024
1 parent be5fe8d commit f65b881
Show file tree
Hide file tree
Showing 4 changed files with 10 additions and 96 deletions.
9 changes: 2 additions & 7 deletions src/Data/TemplateData.js
Original file line number Diff line number Diff line change
Expand Up @@ -495,12 +495,7 @@ class TemplateData {

if (extension === "js" || extension === "cjs" || extension === "mjs") {
// JS data file or require’d JSON (no preprocessing needed)
let localPath = TemplatePath.absolutePath(path);
let exists = this._fsExistsCache.exists(localPath);
// Make sure that relative lookups benefit from cache
this._fsExistsCache.markExists(path, exists);

if (!exists) {
if (!this._fsExistsCache.exists(path)) {
return {};
}

Expand All @@ -515,7 +510,7 @@ class TemplateData {
}

// We always need to use `import()`, as `require` isn’t available in ESM.
let returnValue = await EleventyImport(localPath, type);
let returnValue = await EleventyImport(path, type);

// TODO special exception for Global data `permalink.js`
// module.exports = (data) => `${data.page.filePathStem}/`; // Does not work
Expand Down
1 change: 0 additions & 1 deletion src/TemplateConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,6 @@ class TemplateConfig {
get existsCache() {
if (!this._existsCache) {
this._existsCache = new ExistsCache();
this._existsCache.setDirectoryCheck(true);
}
return this._existsCache;
}
Expand Down
57 changes: 4 additions & 53 deletions src/Util/ExistsCache.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import fs from "graceful-fs";
import PathNormalizer from "./PathNormalizer.js";

// Checks both files and directories
class ExistsCache {
Expand All @@ -8,77 +7,29 @@ class ExistsCache {
this.lookupCount = 0;
}

setDirectoryCheck(check) {
this.shouldCacheDirectories = !!check;
}

get size() {
return this._cache.size;
}

parentsDoNotExist(path) {
if (!this.shouldCacheDirectories) {
return false;
}

let allPaths = PathNormalizer.getAllPaths(path).filter((entry) => entry !== path);
for (let parentPath of allPaths) {
if (this._cache.has(parentPath)) {
if (this._cache.get(parentPath) === false) {
return true; // we know this parent doesn’t exist
}
}
}

// if you’ve made it here: we don’t know if the parents exist or not
return undefined;
}

has(path) {
return this._cache.has(path);
}

// Relative paths (to root directory) expected
exists(path) {
path = PathNormalizer.fullNormalization(path);

if (this.parentsDoNotExist(path)) {
// we don’t need to check if we already know the parent directories do not exist
return false;
} else if (!this._cache.has(path)) {
if (!this._cache.has(path)) {
let exists = fs.existsSync(path);
this.lookupCount++;

this.markExistsWithParentDirectories(path, exists);
this.markExists(path, exists);

return exists;
}

return this._cache.get(path);
}

// if a file exists, we can mark the parent directories as existing also
// if a file does not exist, we don’t know if the parent directories exist or not (yet)
markExistsWithParentDirectories(path, exists = true) {
path = PathNormalizer.fullNormalization(path);

if (!this.shouldCacheDirectories || !exists) {
// does not exist: only mark path
this.markExists(path, false, true);
return;
}

// exists: mark path and parents
let paths = PathNormalizer.getAllPaths(path);
for (let fullpath of paths) {
this.markExists(fullpath, true, true);
}
}

markExists(path, exists = true, alreadyNormalized = false) {
if (!alreadyNormalized) {
path = PathNormalizer.fullNormalization(path);
}

markExists(path, exists = true) {
this._cache.set(path, !!exists);
}
}
Expand Down
39 changes: 4 additions & 35 deletions test/ExistsCacheTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import ExistsCache from "../src/Util/ExistsCache.js";

test("Simple check (with directory checking)", async t => {
let cache = new ExistsCache();
cache.setDirectoryCheck(true);

t.is(cache.exists("test"), true);
t.is(cache.size, 1);
t.is(cache.lookupCount, 1);
t.is(cache.exists("test"), true);
t.is(cache.size, 1);
t.is(cache.lookupCount, 1);
Expand All @@ -17,48 +19,15 @@ test("Simple check (with directory checking)", async t => {
t.is(cache.lookupCount, 3);
});

test("Simple check (parent directory is valid)", async t => {
let cache = new ExistsCache();
cache.setDirectoryCheck(true);

t.is(cache.exists("test/stubs"), true);
t.is(cache.size, 2);
t.is(cache.lookupCount, 1);

// we already know this parent folder exists
t.is(cache.exists("test"), true);
t.is(cache.size, 2);
t.is(cache.lookupCount, 1);

// we don’t know if this exists
t.is(cache.exists("test/stubs/does-not-exist-ever-hslkadjflk"), false);
t.is(cache.size, 3);
t.is(cache.lookupCount, 2);
});

test("Simple check (parent directory already invalidated)", async t => {
let cache = new ExistsCache();
cache.setDirectoryCheck(true);

t.is(cache.exists("test/folder-does-not-exist-askdfjkladjs"), false);
t.is(cache.size, 1);
t.is(cache.lookupCount, 1);

// we already know this *doesn’t* exist.
t.is(cache.exists("test/folder-does-not-exist-askdfjkladjs/file-we-already-know-does-not-exist.liquid"), false);
t.is(cache.size, 1);
t.is(cache.lookupCount, 1);
});


test("Simple check (without directory checking)", async t => {
let cache = new ExistsCache();
// cache.setDirectoryCheck(false);

t.is(cache.exists("test/stubs"), true);
t.is(cache.size, 1);
t.is(cache.lookupCount, 1);
t.is(cache.exists("test"), true);
t.is(cache.size, 2);
t.is(cache.size, 2);
t.is(cache.lookupCount, 2);
});

0 comments on commit f65b881

Please sign in to comment.