Skip to content

Commit

Permalink
fix: when revalidating, revalidate all previously visited pages (#1507)
Browse files Browse the repository at this point in the history
  • Loading branch information
abvthecity authored Sep 19, 2024
1 parent b8e74f5 commit bc22525
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DocsKVCache } from "@/server/DocsCache";
import { Revalidator } from "@/server/revalidator";
import { getXFernHostNode } from "@/server/xfernhost/node";
import * as FernNavigation from "@fern-api/fdr-sdk/navigation";
Expand Down Expand Up @@ -62,11 +63,17 @@ const handler: NextApiHandler = async (
const slugCollector = NodeCollector.collect(node);
const slugs = slugCollector.getPageSlugs();

const cache = DocsKVCache.getInstance(xFernHost);
const previouslyVisitedSlugs = (await cache.getVisitedSlugs()).filter((slug) => !slugs.includes(slug));

const results: FernDocs.RevalidationResult[] = [];
for (const batch of chunk(slugs, DEFAULT_BATCH_SIZE)) {
results.push(...(await revalidate.batch(batch)));
}

// Revalidate previously visited slugs
await revalidate.batch(previouslyVisitedSlugs);

const successfulRevalidations = results.filter(isSuccessResult);
const failedRevalidations = results.filter(isFailureResult);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DocsKVCache } from "@/server/DocsCache";
import { Revalidator } from "@/server/revalidator";
import { getXFernHostNode } from "@/server/xfernhost/node";
import * as FernNavigation from "@fern-api/fdr-sdk/navigation";
Expand Down Expand Up @@ -70,11 +71,20 @@ const handler: NextApiHandler = async (

const node = FernNavigation.utils.convertLoadDocsForUrlResponse(docs.body);
const slugs = NodeCollector.collect(node).getPageSlugs();
const revalidate = new Revalidator(res, xFernHost);

if (offset === 0) {
const cache = DocsKVCache.getInstance(xFernHost);
const previouslyVisitedSlugs = (await cache.getVisitedSlugs()).filter((slug) => !slugs.includes(slug));

// Revalidate previously visited slugs
await revalidate.batch(previouslyVisitedSlugs);
}

const total = slugs.length;
const start = offset * limit;
const batch = slugs.slice(start, start + limit);

const revalidate = new Revalidator(res, xFernHost);
const results = await revalidate.batch(batch);

return res.status(200).json({ total, results });
Expand Down
15 changes: 14 additions & 1 deletion packages/ui/docs-bundle/src/pages/static/[host]/[[...slug]].tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import { DocsKVCache } from "@/server/DocsCache";
import { getDocsPageProps } from "@/server/getDocsPageProps";
import { withSSGProps } from "@/server/withSSGProps";
import { FernNavigation } from "@fern-api/fdr-sdk";
import { DocsPage } from "@fern-ui/ui";
import { GetStaticPaths, GetStaticProps } from "next";
import { ComponentProps } from "react";
Expand All @@ -11,7 +13,18 @@ export const getStaticProps: GetStaticProps<ComponentProps<typeof DocsPage>> = a
const xFernHost = params.host as string;
const slugArray = params.slug == null ? [] : Array.isArray(params.slug) ? params.slug : [params.slug];

return withSSGProps(getDocsPageProps(xFernHost, slugArray));
const props = await withSSGProps(getDocsPageProps(xFernHost, slugArray));

const cache = DocsKVCache.getInstance(xFernHost);
const slug = FernNavigation.utils.slugjoin(...slugArray);

if ("props" in props) {
cache.addVisitedSlugs(slug);
} else if ("notFound" in props || "redirect" in props) {
cache.removeVisitedSlugs(slug);
}

return props;
};

export const getStaticPaths: GetStaticPaths = () => {
Expand Down
38 changes: 38 additions & 0 deletions packages/ui/docs-bundle/src/server/DocsCache.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import type { FernNavigation } from "@fern-api/fdr-sdk";
import { kv } from "@vercel/kv";

const DEPLOYMENT_ID = process.env.VERCEL_DEPLOYMENT_ID ?? "development";
const PREFIX = `docs:${DEPLOYMENT_ID}`;

export class DocsKVCache {
private static instance: Map<string, DocsKVCache>;

private constructor(private domain: string) {}

public static getInstance(domain: string): DocsKVCache {
if (!DocsKVCache.instance) {
DocsKVCache.instance = new Map<string, DocsKVCache>();
}

const instance = DocsKVCache.instance.get(domain);
if (!instance) {
const newInstance = new DocsKVCache(domain);
DocsKVCache.instance.set(domain, newInstance);
return newInstance;
} else {
return instance;
}
}

public async addVisitedSlugs(...slug: FernNavigation.Slug[]): Promise<void> {
await kv.sadd(`${PREFIX}:${this.domain}:visited-slugs`, ...slug);
}

public async getVisitedSlugs(): Promise<FernNavigation.Slug[]> {
return kv.smembers(`${PREFIX}:${this.domain}:visited-slugs`);
}

public async removeVisitedSlugs(...slug: FernNavigation.Slug[]): Promise<void> {
await kv.srem(`${PREFIX}:${this.domain}:visited-slugs`, ...slug);
}
}
64 changes: 25 additions & 39 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit bc22525

Please sign in to comment.