From e65ea48fae5a279ad4e50594b03621904f84e477 Mon Sep 17 00:00:00 2001 From: Jacky Zhao Date: Sun, 20 Aug 2023 14:27:44 -0700 Subject: [PATCH] fix: add async-mutex to builds on large vaults --- package-lock.json | 14 ++++++++++++++ package.json | 1 + quartz/bootstrap-cli.mjs | 4 ++++ quartz/build.ts | 12 ++++++++---- quartz/components/RecentNotes.tsx | 4 ++-- 5 files changed, 29 insertions(+), 6 deletions(-) diff --git a/package-lock.json b/package-lock.json index c7ef802a9..fa661da49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "@clack/prompts": "^0.6.3", "@floating-ui/dom": "^1.4.0", "@napi-rs/simple-git": "^0.1.8", + "async-mutex": "^0.4.0", "chalk": "^4.1.2", "chokidar": "^3.5.3", "cli-spinner": "^0.2.10", @@ -1628,6 +1629,14 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/async-mutex": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/async-mutex/-/async-mutex-0.4.0.tgz", + "integrity": "sha512-eJFZ1YhRR8UN8eBLoNzcDPcy/jqjsg6I1AP+KvWQX80BqOSW1oJPJXDylPUEeMr2ZQvHgnQ//Lp6f3RQ1zI7HA==", + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -5582,6 +5591,11 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, "node_modules/tsx": { "version": "3.12.7", "resolved": "https://registry.npmjs.org/tsx/-/tsx-3.12.7.tgz", diff --git a/package.json b/package.json index 4f9f109bd..7fb51275b 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@clack/prompts": "^0.6.3", "@floating-ui/dom": "^1.4.0", "@napi-rs/simple-git": "^0.1.8", + "async-mutex": "^0.4.0", "chalk": "^4.1.2", "chokidar": "^3.5.3", "cli-spinner": "^0.2.10", diff --git a/quartz/bootstrap-cli.mjs b/quartz/bootstrap-cli.mjs index ab6328698..f7f550423 100755 --- a/quartz/bootstrap-cli.mjs +++ b/quartz/bootstrap-cli.mjs @@ -16,6 +16,7 @@ import http from "http" import serveHandler from "serve-handler" import { WebSocketServer } from "ws" import { randomUUID } from "crypto" +import { Mutex } from "async-mutex" const ORIGIN_NAME = "origin" const UPSTREAM_NAME = "upstream" @@ -391,8 +392,10 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started. ], }) + const buildMutex = new Mutex() const timeoutIds = new Set() const build = async (clientRefresh) => { + await buildMutex.acquire() const result = await ctx.rebuild().catch((err) => { console.error(`${chalk.red("Couldn't parse Quartz configuration:")} ${fp}`) console.log(`Reason: ${chalk.grey(err)}`) @@ -415,6 +418,7 @@ See the [documentation](https://quartz.jzhao.xyz) for how to get started. const { default: buildQuartz } = await import(cacheFile + `?update=${randomUUID()}`) await buildQuartz(argv, clientRefresh) clientRefresh() + buildMutex.release() } const rebuild = (clientRefresh) => { diff --git a/quartz/build.ts b/quartz/build.ts index b5b1f9eea..78437f8aa 100644 --- a/quartz/build.ts +++ b/quartz/build.ts @@ -16,6 +16,7 @@ import { Argv, BuildCtx } from "./util/ctx" import { glob, toPosixPath } from "./util/glob" import { trace } from "./util/trace" import { options } from "./util/sourcemap" +import { Mutex } from "async-mutex" async function buildQuartz(argv: Argv, clientRefresh: () => void) { const ctx: BuildCtx = { @@ -77,10 +78,11 @@ async function startServing( } const initialSlugs = ctx.allSlugs - let timeoutIds: Set> = new Set() - let toRebuild: Set = new Set() - let toRemove: Set = new Set() - let trackedAssets: Set = new Set() + const buildMutex = new Mutex() + const timeoutIds: Set> = new Set() + const toRebuild: Set = new Set() + const toRemove: Set = new Set() + const trackedAssets: Set = new Set() async function rebuild(fp: string, action: "add" | "change" | "delete") { // don't do anything for gitignored files if (ignored(fp)) { @@ -111,6 +113,7 @@ async function startServing( // debounce rebuilds every 250ms timeoutIds.add( setTimeout(async () => { + await buildMutex.acquire() const perf = new PerfTimer() console.log(chalk.yellow("Detected change, rebuilding...")) try { @@ -143,6 +146,7 @@ async function startServing( clientRefresh() toRebuild.clear() toRemove.clear() + buildMutex.release() }, 250), ) } diff --git a/quartz/components/RecentNotes.tsx b/quartz/components/RecentNotes.tsx index 5e992b48b..2b61b39cb 100644 --- a/quartz/components/RecentNotes.tsx +++ b/quartz/components/RecentNotes.tsx @@ -25,13 +25,13 @@ export default ((userOpts?: Partial) => { const opts = { ...defaultOptions, ...userOpts } function RecentNotes(props: QuartzComponentProps) { const { allFiles, fileData, displayClass } = props - const pages = allFiles.filter(opts.filter).sort(opts.sort).slice(0, opts.limit) + const pages = allFiles.filter(opts.filter).sort(opts.sort) const remaining = Math.max(0, pages.length - opts.limit) return (

{opts.title}

    - {pages.map((page) => { + {pages.slice(0, opts.limit).map((page) => { const title = page.frontmatter?.title const tags = page.frontmatter?.tags ?? []