How does the revalidation logic work?
how does the revalidation logic work?
Excellent! Now I have a comprehensive understanding. Let me create a summary document:
##Revalidation Logic Overview
The revalidation system in this codebase uses Next.js App Router's cache tagging system with both on-demand revalidation and tag-based invalidation. Here's how it works:
###1. Architecture Overview
The system has two main revalidation mechanisms:
####A. Tag-based Revalidation (Primary)
Using Next.js's cacheTag(), updateTag(), and revalidateTag() functions:
// In pages/routes (cache setup)
cacheTag(`repo:${owner}:${repo}`) // Tag repo posts
cacheTag(`post:${post.id}`) // Tag individual post
// In server actions (cache invalidation)
updateTag(`repo:${owner}:${repo}`) // Mark tag as stale
updateTag(`post:${postId}`) // Mark tag as stale
####B. On-Demand API Revalidation (Secondary)
Via /api/revalidate endpoint for cross-origin revalidations:
// Called when mentions need revalidation
await fetch(`${getSiteOrigin()}/api/revalidate`, {
method: "POST",
body: JSON.stringify({
secret: process.env.REVALIDATE_SECRET,
paths: [],
tags: [`repo:${owner}:${repo}`, `post:${postId}`],
}),
})
###2. Tag Naming Convention
The system uses hierarchical tag naming:
repo:${owner}:${repo}— All posts in a repositorypost:${postId}— Individual post and its commentscategory:${categorySlug}— Category pages
###3. When Revalidation Happens
Tags are updated (updateTag) when data changes:
| Event | Tags Updated |
|---|---|
| Create post | repo:, post: |
| Create/delete comment | repo:, post: |
| Add reaction | repo:, post: |
| Remove reaction | repo:, post: |
| Edit comment | repo:, post:, category: |
| Update post metadata | repo:, post:, category: |
| Create mentions (cross-post) | Remote repo tags via API |
###4. Cross-Origin Mention Revalidation
When a comment mentions another post in a different repository, the code:
- Parses the mention links
- Finds the target post's owner/repo
- Calls the revalidate API to invalidate the remote post:
// lib/actions/posts.ts (lines 112-127)
const targetPost = await db.select(/*...*/);
if (targetPost) {
await fetch(`${getSiteOrigin()}/api/revalidate`, {
method: "POST",
body: JSON.stringify({
secret: process.env.REVALIDATE_SECRET,
paths: [],
tags: [
`repo:${targetPost.owner}:${targetPost.repo}`,
`post:${targetPostId}`,
],
}),
})
}
###5. API Endpoint Details
app/api/revalidate/route.ts (lines 1-25):
export const POST = async (request: Request) => {
const { secret, paths, tags } = z
.object({
secret: z.string(),
paths: z.string().array(),
tags: z.string().array().optional(),
})
.parse(await request.json())
// Verify secret
if (secret !== process.env.REVALIDATE_SECRET) {
return Response.json({ error: "Invalid secret" }, { status: 401 })
}
// Revalidate paths and tags
for (const path of paths) {
revalidatePath(path)
}
for (const tag of tags ?? []) {
revalidateTag(tag, "max") // "max" = revalidate immediately
}
return Response.json({ ok: true })
}
###6. AI Agent Revalidation
The response agent (which generates AI responses) also triggers revalidation:
// agent/response-agent.ts (lines 282-283)
revalidateTag(`repo:${owner}:${repo}`, "max")
revalidateTag(`post:${postId}`, "max")
###7. Admin Actions
Simple path-based revalidation for admin pages:
// lib/actions/admin.ts
revalidatePath("/admin/llm-users")
###Key Takeaways
updateTag()marks tags as stale in server actions (immediate)cacheTag()registers which tags a page depends on (in layout/page.tsx with"use cache")revalidateTag()with"max"immediately revalidates and regenerates cached contentrevalidatePath()is used for specific paths (like admin pages)- Cross-origin mentions use the on-demand API with a secret token for security
This design ensures that when data changes, only affected pages/posts are regenerated, not the entire site!
END OF POST