Skip to content

feat(content): pin instances per commit with withRef() - #42

Open
atinux wants to merge 2 commits into
feat/client-side-fts-searchfrom
feat/with-ref
Open

feat(content): pin instances per commit with withRef()#42
atinux wants to merge 2 commits into
feat/client-side-fts-searchfrom
feat/with-ref

Conversation

@atinux

@atinux atinux commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

Written by an AI agent on behalf of @atinux, who is reviewing it.

Stacked on #22. Depends on comark-content@98457f7 from comarkdown/comark-content#120 (already bumped here via pkg.pr.new). Merge #22 first; GitHub will retarget this to main.

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:

  • One base instance per process. Every serving instance is base.withRef(sha): same source, plugins and cache driver, pinned to a commit, with its own index and its own cache namespace (ref:<sha>: under content:<parserVersion>). cacheDriver(sha) is gone for content; shaCacheStorage() keeps a per-SHA driver for its gh: keys.
  • The build snapshot carries its commit. modules/snapshot parses on an instance pinned to the resolved content commit, so the artifact is stamped with ref. At that 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 (frontmatter only) and reuses every body whose meta.hash is 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.
  • Previews share the default base path. /blob/:sha, /tree/:branch and /pr/:number strip their mount segment and dispatch through servePreview(), which also keeps the head-of-branch shortcut to the prod instance. getPreviewContent(sha) loses its basePath argument.
  • dispose() on the instance the prod swap drops, on preview LRU eviction (which fixes the watcher-leak caveat noted in the old createSourceContent), and on the webhook's throwaway diff instance.
  • In development, the base source is fs() with a withRef that reads local git history, so withRef(sha) previews keep working without a second code path.

createSourceContent() is replaced by contentAt(sha).

Verified

  • vitest run: 19 files, 177 tests pass. eslint . and nuxt typecheck playground pass.
  • nuxt build playground: the module logs Content snapshot f97dc86: 200 kB; the emitted artifact has ref: f97dc86… and a meta.hash on all 20 items.
  • Built server, VERCEL_GIT_COMMIT_REF set to that commit, network blocked: /api/content/get/... and /navigation return 200. Zero GitHub calls.
  • Same server pinned to 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:after cache 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.

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).
@coldtea-pr-lens

coldtea-pr-lens Bot commented Sep 7, 2026

Copy link
Copy Markdown

◈ PR Lens

🟢 +0 new · 🟠 ~5 changed · 🔴 -0 removed · 2 flows · 10 files · commit 61be700


Architecture

Architecture diagram for comarkdown/comark-docs at 61be700

5 components touched across 6 lanes.

Open the interactive canvas


Inside the changed components — 2 views

Component view — Pinned content and caching

Base engine derives commit-pinned instances with unified runtime cache and explicit disposal.

Architecture view of Component view — Pinned content and caching in comarkdown/comark-docs

Component view — Preview dispatch and registry

Preview routes use unified dispatch with LRU instance caching and head-of-branch reuse.

Architecture view of Component view — Preview dispatch and registry in comarkdown/comark-docs

Data flow

Data flow diagram for comarkdown/comark-docs at 61be700

Serving content previews · Revalidating content on webhook update

Open the interactive canvas


The other flows — 1 sequence

Revalidating content on webhook update

Sequence diagram of Revalidating content on webhook update in comarkdown/comark-docs

Drill down
Server Routes & APIs — 2 components
🟡 CHANGED Content API

Preview and production content endpoints; preview routes now delegate to a shared preview dispatcher.

🟡 CHANGED Revalidate Webhook

Webhook endpoint that creates an ephemeral pinned content instance to diff manifest changes and disposes it.

Content Engine — 2 components
🟡 CHANGED comark-content Engine

Base content engine that creates commit-pinned instances with shared cache drivers and build snapshot hydration.

🟡 CHANGED Preview Registry

LRU registry holding up to 8 pinned preview instances, disposing evicted instances and reusing production head.

Cache & Datastores — 1 component
🟡 CHANGED Vercel Runtime Content Cache

Runtime cache driver under content:v3, partitioned across commits using ref:⁠sha: key prefixes.


View

  • Architecture lens
  • Data flow lens
  • Expand every detail
  • Show unchanged neighbours

Tip

The diagrams follow your GitHub theme, so dark mode gets the dark render and light mode the light one, and the moving dots show this pull request's data in motion.

🪧 More tips
  • Run PR Lens on your own machine: npx skills add coldteadotai/pr-lens installs the agent skill. Then tell your coding agent: "Diagram the change you just made with PR Lens and attach it to the pull request."
  • Draw a diff before it is even a pull request: npx @coldtea/pr-lens-cli analyze --base origin/main reads the diff with your own model key, and npx @coldtea/pr-lens-cli render .pr-lens/graph.json draws the same lenses on your machine.
  • The boxes under View are live. Tick Architecture lens or Data flow lens to choose which diagrams appear, or Expand every detail to open every drill-down at once. The comment redraws in place a few seconds later.
  • Show unchanged neighbours lists the components this change did not touch alongside the ones it did, so the drill-down shows what the changed code sits next to.
  • GitHub will not let you zoom an image in a comment. The link under each diagram opens it on an interactive canvas, where you can zoom, pan and step through the flow.
  • The CLI's render picks up .github/pr-lens.yml automatically and applies your corrections (renames, exclusions, lane pins) at draw time.
  • Would you rather run it from CI on a key of your own? Add .github/workflows/pr-lens.yml with coldteadotai/pr-lens/packages/action@v0 and a model key in your repository secrets, say GEMINI_API_KEY. The Action asks Gemini by default, or OpenAI and any endpoint speaking /chat/completions through its provider input.
  • PR Lens is free for open source. A star on the repository is what keeps it going.
  • Push a new commit and the whole comment re-renders for the new head. An older run never overwrites a newer one, so a slow render cannot put a stale diagram back.

◈ Rendered by PR Lens · crafted with ❤️ by the Coldtea team · Come say hi on Discord

@vercel

vercel Bot commented Sep 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
comark-docs-layer Ready Ready Preview Sep 7, 2026 8:06pm UTC

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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant