feat(content): pin instances per commit with withRef() - #42
Conversation
Every serving instance is now base.withRef(sha): the same source, plugins and cache driver, pinned to a commit, with its own index and cache namespace. The per-SHA driver factory goes away for content (the ref namespace replaces it); shaCacheStorage keeps its own for gh: keys. The build snapshot is produced on an instance pinned to the content commit, so it carries that ref. At the same commit it is the index and a cold start makes no GitHub call; at a later commit comark-content walks the commit for the index and reuses every body whose source text did not change, so a push costs one frontmatter walk plus a parse of the changed files instead of a full parse. Previews share the default base path: the /blob, /tree and /pr routes strip their mount segment and dispatch to the pinned instance through servePreview(). The prod swap and the preview LRU dispose() the instance they drop; the webhook's diff instance is disposed after use. Depends on comark-content@98457f7 (comarkdown/comark-content#120).
◈ PR Lens
Architecture 5 components touched across 6 lanes. Inside the changed components — 2 viewsComponent view — Pinned content and caching Base engine derives commit-pinned instances with unified runtime cache and explicit disposal. Component view — Preview dispatch and registry Preview routes use unified dispatch with LRU instance caching and head-of-branch reuse. Data flow
The other flows — 1 sequence
Drill down
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Without a sha it backs comark's entries (withRef adds the ref prefix); with one it backs the per-commit gh: data. Same base, one function.
Stacked on #22. Depends on
comark-content@98457f7from comarkdown/comark-content#120 (already bumped here via pkg.pr.new). Merge #22 first; GitHub will retarget this tomain.What
The layer already ran "one instance per content commit, swap when the branch moves". This PR moves the mechanics into
comark-content, which now provides them:base.withRef(sha): same source, plugins and cache driver, pinned to a commit, with its own index and its own cache namespace (ref:<sha>:undercontent:<parserVersion>).cacheDriver(sha)is gone for content;shaCacheStorage()keeps a per-SHA driver for itsgh:keys.modules/snapshotparses on an instance pinned to the resolved content commit, so the artifact is stamped withref. At that commit it is the index and a cold start makes no GitHub call. At a later commitcomark-contentwalks the commit for the index (frontmatter only) and reuses every body whosemeta.hashis unchanged, so a push costs one walk plus a parse of the changed files instead of a full parse. The artifact lives at a fixed path now (comark-content/default/snapshot.json), no per-SHA directory./blob/:sha,/tree/:branchand/pr/:numberstrip their mount segment and dispatch throughservePreview(), which also keeps the head-of-branch shortcut to the prod instance.getPreviewContent(sha)loses itsbasePathargument.dispose()on the instance the prod swap drops, on preview LRU eviction (which fixes the watcher-leak caveat noted in the oldcreateSourceContent), and on the webhook's throwaway diff instance.fs()with awithRefthat reads local git history, sowithRef(sha)previews keep working without a second code path.createSourceContent()is replaced bycontentAt(sha).Verified
vitest run: 19 files, 177 tests pass.eslint .andnuxt typecheck playgroundpass.nuxt build playground: the module logsContent snapshot f97dc86: 200 kB; the emitted artifact hasref: f97dc86…and ameta.hashon all 20 items.VERCEL_GIT_COMMIT_REFset to that commit, network blocked:/api/content/get/...and/navigationreturn 200. Zero GitHub calls.main(a later commit): 200 with the network; with it blocked it fails on the tree walk, as expected, since the index must come from the commit.Not in this PR
read:aftercache tags: the layer purges by URL from the webhook diff, so nothing to wire yet.clean()for deleted preview branches: nothing enumerates stale refs today; the Runtime Cache TTL (24 h) covers it.