Skip to content

Commit

Permalink
Each time we run a loader, save the loader information to the cache. …
Browse files Browse the repository at this point in the history
…Using a big JSON file for now, but we might want to use a sqlite db instead to solve the race conditions.

The loader information will be used to complete the build manifest.
  • Loading branch information
Fil committed Oct 22, 2024
1 parent 031ac6d commit ec87bf9
Showing 1 changed file with 48 additions and 2 deletions.
50 changes: 48 additions & 2 deletions src/loader.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {createHash} from "node:crypto";
import type {FSWatcher, WatchListener, WriteStream} from "node:fs";
import {createReadStream, existsSync, statSync, watch} from "node:fs";
import {open, readFile, rename, unlink} from "node:fs/promises";
import type {FileHandle} from "node:fs/promises";
import {open, readFile, rename, unlink, writeFile} from "node:fs/promises";
import {dirname, extname, join} from "node:path/posix";
import {createGunzip} from "node:zlib";
import {spawn} from "cross-spawn";
import JSZip from "jszip";
import {extract} from "tar-stream";
import {enoent} from "./error.js";
import {enoent, isEnoent} from "./error.js";
import {maybeStat, prepareOutput, visitFiles} from "./files.js";
import {FileWatchers} from "./fileWatchers.js";
import {formatByteSize} from "./format.js";
Expand Down Expand Up @@ -463,12 +464,57 @@ abstract class AbstractLoader implements Loader {
effects.logger.log(`${red("error")} ${faint(`in ${formatElapsed(start)}:`)} ${red(error.message)}`);
}
);
command.then(() => saveLoadInfo(this));

Check failure on line 467 in src/loader.ts

View workflow job for this annotation

GitHub Actions / test (20, ubuntu-latest)

Argument of type 'this' is not assignable to parameter of type '{ root: string; targetPath: string; loader: string; params?: { [key: string]: string; } | undefined; }'.

Check failure on line 467 in src/loader.ts

View workflow job for this annotation

GitHub Actions / test (20, windows-latest)

Argument of type 'this' is not assignable to parameter of type '{ root: string; targetPath: string; loader: string; params?: { [key: string]: string; } | undefined; }'.

Check failure on line 467 in src/loader.ts

View workflow job for this annotation

GitHub Actions / test (21, ubuntu-latest)

Argument of type 'this' is not assignable to parameter of type '{ root: string; targetPath: string; loader: string; params?: { [key: string]: string; } | undefined; }'.

Check failure on line 467 in src/loader.ts

View workflow job for this annotation

GitHub Actions / test (21, windows-latest)

Argument of type 'this' is not assignable to parameter of type '{ root: string; targetPath: string; loader: string; params?: { [key: string]: string; } | undefined; }'.
return command;
}

abstract exec(output: WriteStream, options?: LoadOptions, effects?: LoadEffects): Promise<void>;
}

/**
* Saves the loaders information for the *targetPath* page, module or file, to
* the cache. The information will be added to the build manifest.
*/
async function saveLoadInfo({
root,
targetPath,
path: loader,

Check failure on line 481 in src/loader.ts

View workflow job for this annotation

GitHub Actions / test (20, ubuntu-latest)

Property 'path' does not exist on type '{ root: string; targetPath: string; loader: string; params?: { [key: string]: string; } | undefined; }'.

Check failure on line 481 in src/loader.ts

View workflow job for this annotation

GitHub Actions / test (20, windows-latest)

Property 'path' does not exist on type '{ root: string; targetPath: string; loader: string; params?: { [key: string]: string; } | undefined; }'.

Check failure on line 481 in src/loader.ts

View workflow job for this annotation

GitHub Actions / test (21, ubuntu-latest)

Property 'path' does not exist on type '{ root: string; targetPath: string; loader: string; params?: { [key: string]: string; } | undefined; }'.

Check failure on line 481 in src/loader.ts

View workflow job for this annotation

GitHub Actions / test (21, windows-latest)

Property 'path' does not exist on type '{ root: string; targetPath: string; loader: string; params?: { [key: string]: string; } | undefined; }'.
params
}: {
root: string;
targetPath: string;
loader: string;
params?: {[key: string]: string};
}) {
let buildInfo: {[path: string]: {loader: string; params?: {[key: string]: string}}} = {};
const cachePath = join(root, ".observablehq", "cache", "_loaders.json");
const lock = `${cachePath}.lock`;
let handle: FileHandle | null = null;
let retry = 10;
await prepareOutput(cachePath);
do {
if (--retry === 0) throw new Error(`Could not acquire ${lock}`);
try {
handle = await open(lock, "wx");
} catch (error) {
if (error?.["code"] !== "EEXIST") throw error;
await new Promise((resolve) => setTimeout(resolve, 100 * (1 + Math.random())));
}
} while (!handle);
try {
buildInfo = JSON.parse(await readFile(cachePath, "utf-8"));
} catch (error) {
if (!isEnoent(error)) throw error;
} finally {
buildInfo[targetPath] = {loader, params};
try {
await writeFile(cachePath, JSON.stringify(buildInfo), "utf-8");
} finally {
await unlink(lock);
}
}
}

interface CommandLoaderOptions extends LoaderOptions {
command: string;
args: string[];
Expand Down

0 comments on commit ec87bf9

Please sign in to comment.