fix: handle caching of card grids on content page blocks
This commit is contained in:
@@ -1,11 +1,31 @@
|
||||
import "server-only"
|
||||
|
||||
import deepmerge from "deepmerge"
|
||||
|
||||
import { request } from "./request"
|
||||
|
||||
import type { BatchRequestDocument } from "graphql-request"
|
||||
|
||||
import type { Data } from "@/types/request"
|
||||
|
||||
function arrayMerge(
|
||||
target: any[],
|
||||
source: any[],
|
||||
options: deepmerge.ArrayMergeOptions | undefined
|
||||
) {
|
||||
const destination = target.slice()
|
||||
source.forEach((item, index) => {
|
||||
if (typeof destination[index] === "undefined") {
|
||||
destination[index] = options?.cloneUnlessOtherwiseSpecified(item, options)
|
||||
} else if (options?.isMergeableObject(item)) {
|
||||
destination[index] = deepmerge(target[index], item, options)
|
||||
} else if (target.indexOf(item) === -1) {
|
||||
destination.push(item)
|
||||
}
|
||||
})
|
||||
return destination
|
||||
}
|
||||
|
||||
export async function batchRequest<T>(
|
||||
queries: (BatchRequestDocument & { options?: RequestInit })[]
|
||||
): Promise<Data<T>> {
|
||||
@@ -17,15 +37,21 @@ export async function batchRequest<T>(
|
||||
)
|
||||
|
||||
let data = {} as T
|
||||
const reasons = []
|
||||
const reasons: PromiseRejectedResult["reason"][] = []
|
||||
response.forEach((res) => {
|
||||
if (res.status === "fulfilled") {
|
||||
data = Object.assign({}, data, res.value.data)
|
||||
data = deepmerge(data, res.value.data, { arrayMerge })
|
||||
} else {
|
||||
reasons.push(res.reason)
|
||||
}
|
||||
})
|
||||
|
||||
if (reasons.length) {
|
||||
reasons.forEach((reason) => {
|
||||
console.error(`Batch request failed`, reason)
|
||||
})
|
||||
}
|
||||
|
||||
return { data }
|
||||
} catch (error) {
|
||||
console.error("Error in batched graphql request")
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { Lang } from "@/constants/languages"
|
||||
import { batchRequest } from "@/lib/graphql/batchRequest"
|
||||
import {
|
||||
GetContentPage,
|
||||
GetContentPageBlocksBatch1,
|
||||
GetContentPageBlocksBatch2,
|
||||
} from "@/lib/graphql/Query/ContentPage/ContentPage.graphql"
|
||||
import { request } from "@/lib/graphql/request"
|
||||
import { contentstackExtendedProcedureUID, router } from "@/server/trpc"
|
||||
|
||||
import { contentPageSchema } from "./output"
|
||||
@@ -12,30 +12,20 @@ import {
|
||||
fetchContentPageRefs,
|
||||
generatePageTags,
|
||||
getContentPageCounter,
|
||||
validateContentPageRefs,
|
||||
} from "./utils"
|
||||
|
||||
import {
|
||||
TrackingChannelEnum,
|
||||
type TrackingSDKPageData,
|
||||
} from "@/types/components/tracking"
|
||||
import { ContentPageEnum } from "@/types/enums/contentPage"
|
||||
import type {
|
||||
GetBlock,
|
||||
GetContentPageSchema,
|
||||
} from "@/types/trpc/routers/contentstack/contentPage"
|
||||
import type { GetContentPageSchema } from "@/types/trpc/routers/contentstack/contentPage"
|
||||
|
||||
export const contentPageQueryRouter = router({
|
||||
get: contentstackExtendedProcedureUID.query(async ({ ctx }) => {
|
||||
const { lang, uid } = ctx
|
||||
|
||||
const contentPageRefsData = await fetchContentPageRefs(lang, uid)
|
||||
const contentPageRefs = await fetchContentPageRefs(lang, uid)
|
||||
|
||||
const contentPageRefs = validateContentPageRefs(
|
||||
contentPageRefsData,
|
||||
lang,
|
||||
uid
|
||||
)
|
||||
if (!contentPageRefs) {
|
||||
return null
|
||||
}
|
||||
@@ -50,69 +40,42 @@ export const contentPageQueryRouter = router({
|
||||
})
|
||||
)
|
||||
|
||||
const [mainResponse, blocksResponse1, blocksResponse2] = await Promise.all([
|
||||
request<GetContentPageSchema>(
|
||||
GetContentPage,
|
||||
{ locale: lang, uid },
|
||||
{
|
||||
const contentPageRequest = await batchRequest<GetContentPageSchema>([
|
||||
{
|
||||
document: GetContentPage,
|
||||
variables: { locale: lang, uid },
|
||||
options: {
|
||||
cache: "force-cache",
|
||||
next: {
|
||||
tags,
|
||||
},
|
||||
}
|
||||
),
|
||||
request<GetContentPageSchema>(
|
||||
GetContentPageBlocksBatch1,
|
||||
{ locale: lang, uid },
|
||||
{
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
document: GetContentPageBlocksBatch1,
|
||||
variables: { locale: lang, uid },
|
||||
options: {
|
||||
cache: "force-cache",
|
||||
next: {
|
||||
tags,
|
||||
},
|
||||
}
|
||||
),
|
||||
request<GetContentPageSchema>(
|
||||
GetContentPageBlocksBatch2,
|
||||
{ locale: lang, uid },
|
||||
{
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
document: GetContentPageBlocksBatch2,
|
||||
variables: { locale: lang, uid },
|
||||
options: {
|
||||
cache: "force-cache",
|
||||
next: {
|
||||
tags,
|
||||
},
|
||||
}
|
||||
),
|
||||
},
|
||||
},
|
||||
])
|
||||
|
||||
const blocksOrder = mainResponse.data.content_page.blocks?.map(
|
||||
(block) => block.__typename
|
||||
)
|
||||
|
||||
let sortedBlocks
|
||||
if (blocksOrder) {
|
||||
const blocks = [
|
||||
blocksResponse1.data.content_page.blocks,
|
||||
blocksResponse2.data.content_page.blocks,
|
||||
]
|
||||
.flat(2)
|
||||
.filter((obj) => !(obj && Object.keys(obj).length < 2))
|
||||
// Remove empty objects and objects with only typename
|
||||
|
||||
sortedBlocks = blocksOrder
|
||||
.map((typename: ContentPageEnum.ContentStack.blocks) =>
|
||||
blocks.find((block) => block?.__typename === typename)
|
||||
)
|
||||
.filter((block): block is GetBlock => !!block)
|
||||
}
|
||||
|
||||
const responseData = {
|
||||
...mainResponse.data,
|
||||
content_page: {
|
||||
...mainResponse.data.content_page,
|
||||
blocks: sortedBlocks,
|
||||
},
|
||||
}
|
||||
|
||||
const contentPage = contentPageSchema.safeParse(responseData)
|
||||
const contentPage = contentPageSchema.safeParse(contentPageRequest.data)
|
||||
if (!contentPage.success) {
|
||||
console.error(
|
||||
`Failed to validate Contentpage Data - (lang: ${lang}, uid: ${uid})`
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { metrics } from "@opentelemetry/api"
|
||||
|
||||
import { Lang } from "@/constants/languages"
|
||||
import { batchRequest } from "@/lib/graphql/batchRequest"
|
||||
import {
|
||||
GetContentPageBlocksRefs,
|
||||
GetContentPageRefs,
|
||||
} from "@/lib/graphql/Query/ContentPage/ContentPage.graphql"
|
||||
import { request } from "@/lib/graphql/request"
|
||||
import { notFound } from "@/server/errors/trpc"
|
||||
|
||||
import { generateTag, generateTagsFromSystem } from "@/utils/generateTag"
|
||||
@@ -44,30 +44,30 @@ export async function fetchContentPageRefs(lang: Lang, uid: string) {
|
||||
query: { lang, uid },
|
||||
})
|
||||
)
|
||||
const [mainRefsResponse, blockRefsResponse] = await Promise.all([
|
||||
request<GetContentPageRefsSchema>(
|
||||
GetContentPageRefs,
|
||||
{ locale: lang, uid },
|
||||
{
|
||||
const res = await batchRequest<GetContentPageRefsSchema>([
|
||||
{
|
||||
document: GetContentPageRefs,
|
||||
variables: { locale: lang, uid },
|
||||
options: {
|
||||
cache: "force-cache",
|
||||
next: {
|
||||
tags: [generateTag(lang, uid)],
|
||||
},
|
||||
}
|
||||
),
|
||||
request<GetContentPageRefsSchema>(
|
||||
GetContentPageBlocksRefs,
|
||||
{ locale: lang, uid },
|
||||
{
|
||||
},
|
||||
},
|
||||
{
|
||||
document: GetContentPageBlocksRefs,
|
||||
variables: { locale: lang, uid },
|
||||
options: {
|
||||
cache: "force-cache",
|
||||
next: {
|
||||
tags: [generateTag(lang, uid)],
|
||||
tags: [generateTag(lang, uid + 1)],
|
||||
},
|
||||
}
|
||||
),
|
||||
},
|
||||
},
|
||||
])
|
||||
if (!mainRefsResponse.data) {
|
||||
const notFoundError = notFound(mainRefsResponse)
|
||||
if (!res.data) {
|
||||
const notFoundError = notFound(res)
|
||||
getContentPageRefsFailCounter.add(1, {
|
||||
lang,
|
||||
uid,
|
||||
@@ -88,22 +88,7 @@ export async function fetchContentPageRefs(lang: Lang, uid: string) {
|
||||
)
|
||||
throw notFoundError
|
||||
}
|
||||
const responseData = {
|
||||
...mainRefsResponse.data,
|
||||
content_page: {
|
||||
...mainRefsResponse.data.content_page,
|
||||
blocks: blockRefsResponse.data.content_page.blocks,
|
||||
},
|
||||
}
|
||||
return responseData
|
||||
}
|
||||
|
||||
export function validateContentPageRefs(
|
||||
data: GetContentPageRefsSchema,
|
||||
lang: Lang,
|
||||
uid: string
|
||||
) {
|
||||
const validatedData = contentPageRefsSchema.safeParse(data)
|
||||
const validatedData = contentPageRefsSchema.safeParse(res.data)
|
||||
if (!validatedData.success) {
|
||||
getContentPageRefsFailCounter.add(1, {
|
||||
lang,
|
||||
@@ -192,6 +177,14 @@ export function getConnections({ content_page }: ContentPageRefs) {
|
||||
}
|
||||
break
|
||||
}
|
||||
case ContentPageEnum.ContentStack.blocks.CardsGrid: {
|
||||
if (block.cards_grid.length) {
|
||||
block.cards_grid.forEach((card) => {
|
||||
connections.push(card)
|
||||
})
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user