feat: implement webhook to clear apollo cache and periodically revalidate static pages
This commit is contained in:
parent
98ec69968c
commit
63261bb140
1
.env
1
.env
|
@ -1,4 +1,5 @@
|
|||
UNBODY_API_KEY=
|
||||
UNBODY_LPE_PROJECT_ID=
|
||||
SIMPLECAST_ACCESS_TOKEN=
|
||||
REVALIDATE_WEBHOOK_TOKEN=
|
||||
NEXT_PUBLIC_SITE_URL=https://press.logos.co
|
|
@ -62,6 +62,7 @@ export const getStaticProps: GetStaticProps<PageProps> = async (ctx) => {
|
|||
props: {
|
||||
notFound: true,
|
||||
},
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -71,6 +72,7 @@ export const getStaticProps: GetStaticProps<PageProps> = async (ctx) => {
|
|||
error: 'Something went wrong!',
|
||||
},
|
||||
notFound: false,
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,6 +83,7 @@ export const getStaticProps: GetStaticProps<PageProps> = async (ctx) => {
|
|||
},
|
||||
},
|
||||
notFound: false,
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import { readFile, writeFile } from 'fs/promises'
|
||||
import type { NextApiRequest, NextApiResponse } from 'next'
|
||||
import path from 'path'
|
||||
|
||||
const WEBHOOK_DATA_PATH = path.join(__dirname, '../../webhook_data.json')
|
||||
const TOKEN = process.env.REVALIDATE_WEBHOOK_TOKEN || ''
|
||||
|
||||
export type WebhookData = {
|
||||
lastUpdate: number
|
||||
}
|
||||
|
||||
const writeWebhookData = async (data: WebhookData) =>
|
||||
await writeFile(WEBHOOK_DATA_PATH, Buffer.from(JSON.stringify(data)))
|
||||
|
||||
export const getWebhookData = async (): Promise<WebhookData> =>
|
||||
JSON.parse((await readFile(WEBHOOK_DATA_PATH, 'utf-8')) || '{}')
|
||||
|
||||
let initialized = false
|
||||
if (!initialized) writeWebhookData({ lastUpdate: +new Date() })
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<any>,
|
||||
) {
|
||||
const {
|
||||
query: { token = '' },
|
||||
} = req
|
||||
|
||||
if (token !== TOKEN) return res.status(401).json({ message: 'Invalid token' })
|
||||
|
||||
writeWebhookData({
|
||||
lastUpdate: +new Date(),
|
||||
})
|
||||
|
||||
res.status(200).json({})
|
||||
}
|
|
@ -73,6 +73,7 @@ export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
|
|||
return {
|
||||
notFound: true,
|
||||
props: { why: 'no article' },
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -98,6 +99,7 @@ export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
|
|||
},
|
||||
error: JSON.stringify(errors),
|
||||
},
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ export const getStaticProps: GetStaticProps<PageProps> = async () => {
|
|||
highlighted,
|
||||
},
|
||||
},
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,7 @@ export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
|
|||
return {
|
||||
notFound: true,
|
||||
props: { why: 'no article' },
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -99,6 +100,7 @@ export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
|
|||
episode,
|
||||
relatedEpisodes,
|
||||
},
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
|
|||
return {
|
||||
notFound: true,
|
||||
props: { why: 'no slug' },
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ export const getStaticProps = async ({ params }: GetStaticPropsContext) => {
|
|||
latestEpisodes: latestEpisodes.map((ep) => ({ ...ep, show: null })),
|
||||
// errors,
|
||||
},
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -140,5 +140,6 @@ export async function getStaticProps() {
|
|||
topics,
|
||||
shows,
|
||||
},
|
||||
revalidate: 10,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { ApolloClient, InMemoryCache } from '@apollo/client'
|
||||
import { minutesToMilliseconds } from 'date-fns'
|
||||
import {
|
||||
CountDocumentsDocument,
|
||||
CountDocumentsQueryVariables,
|
||||
|
@ -12,6 +13,7 @@ import {
|
|||
SearchBlocksDocument,
|
||||
Txt2VecOpenAiGetObjectsTextBlockNearTextInpObj,
|
||||
} from '../../lib/unbody/unbody.generated'
|
||||
import { getWebhookData } from '../../pages/api/webhook'
|
||||
import { ApiResponse, SearchResultItem } from '../../types/data.types'
|
||||
import { LPE } from '../../types/lpe.types'
|
||||
import {
|
||||
|
@ -52,6 +54,8 @@ export class UnbodyService {
|
|||
client: ApolloClient<any> = null as any
|
||||
helpers = UnbodyHelpers
|
||||
|
||||
lastUpdate: number = 0
|
||||
initialDataLastUpdate: number = 0
|
||||
initialDataPromise: CreatePromiseResult<(typeof this)['initialData']> =
|
||||
createPromise()
|
||||
|
||||
|
@ -104,9 +108,26 @@ export class UnbodyService {
|
|||
})
|
||||
|
||||
this.loadInitialData(true)
|
||||
|
||||
if (process.env.NODE_ENV !== 'development') this.checkForUpdates()
|
||||
}
|
||||
|
||||
private checkForUpdates = async () => {
|
||||
const data = await getWebhookData()
|
||||
if (!data) return
|
||||
|
||||
if (data.lastUpdate > this.lastUpdate) {
|
||||
this.lastUpdate = data.lastUpdate
|
||||
await this.clearCache()
|
||||
this.loadInitialData(true)
|
||||
}
|
||||
|
||||
setTimeout(this.checkForUpdates, 1000)
|
||||
}
|
||||
|
||||
private _loadInitialData = async () => {
|
||||
this.initialDataLastUpdate = +new Date()
|
||||
|
||||
const articles: LPE.Article.Data[] = await this.fetchAllArticles()
|
||||
const episodes: LPE.Podcast.Document[] = await this.fetchAllEpisodes()
|
||||
const staticPages = await this.fetchAllStaticPages()
|
||||
|
@ -124,13 +145,26 @@ export class UnbodyService {
|
|||
}
|
||||
|
||||
loadInitialData = async (forced: boolean = false) => {
|
||||
if (forced) {
|
||||
if (
|
||||
forced ||
|
||||
+new Date() - this.initialDataLastUpdate > minutesToMilliseconds(10)
|
||||
) {
|
||||
console.log('load initial data')
|
||||
this.initialDataPromise &&
|
||||
this.initialDataPromise.resolve(this.initialData)
|
||||
|
||||
this.initialDataPromise = createPromise()
|
||||
await this.clearCache()
|
||||
this._loadInitialData()
|
||||
}
|
||||
|
||||
return this.initialDataPromise.promise
|
||||
}
|
||||
|
||||
clearCache = async () => {
|
||||
this.client.cache.reset()
|
||||
}
|
||||
|
||||
private fetchAllStaticPages = async () => {
|
||||
const result: LPE.StaticPage.Document[] = []
|
||||
|
||||
|
@ -220,8 +254,8 @@ export class UnbodyService {
|
|||
data: T | null = null,
|
||||
errors: any = null,
|
||||
): ApiResponse<T> => {
|
||||
if (errors) console.log(errors)
|
||||
if (errors || !data) {
|
||||
console.log(errors)
|
||||
return {
|
||||
data: data as any,
|
||||
errors: JSON.stringify(errors),
|
||||
|
@ -262,7 +296,8 @@ export class UnbodyService {
|
|||
|
||||
getStaticPages = () =>
|
||||
this.handleRequest<LPE.StaticPage.Document[]>(async () => {
|
||||
const { staticPages } = await this.loadInitialData()
|
||||
await this.loadInitialData()
|
||||
const { staticPages } = this.initialData
|
||||
|
||||
return staticPages
|
||||
}, [])
|
||||
|
@ -878,7 +913,8 @@ export class UnbodyService {
|
|||
skip?: number
|
||||
}) =>
|
||||
this.handleRequest(async () => {
|
||||
const { posts } = await this.loadInitialData()
|
||||
await this.loadInitialData()
|
||||
const { posts } = this.initialData
|
||||
|
||||
return posts.slice(skip, skip + limit)
|
||||
}, [])
|
||||
|
|
Loading…
Reference in New Issue