feature: caching
Some checks are pending
Deploy / deploy (push) Waiting to run

This commit is contained in:
Benno Tielen 2026-06-24 14:32:38 +02:00
parent bff425c3bd
commit afc6816451
3 changed files with 111 additions and 70 deletions

View file

@ -1,7 +1,10 @@
import { getPayload } from 'payload'
import { unstable_cache } from 'next/cache'
import config from '@/payload.config'
import { Announcement, Parish } from '@/payload-types'
const CACHE_TTL = 300 // 5 minutes
/**
* Fetch last announcement for a parish
*/
@ -45,20 +48,22 @@ export const fetchLastAnnouncement = async (
/**
* Fetch the last announcement for each parish
*/
export const fetchLastAnnouncements = async (): Promise<
Array<{ parish: Parish; doc: Announcement }>
> => {
const payload = await getPayload({ config })
const parishes = await payload.find({ collection: 'parish', limit: 100 })
export const fetchLastAnnouncements = unstable_cache(
async (): Promise<Array<{ parish: Parish; doc: Announcement }>> => {
const payload = await getPayload({ config })
const parishes = await payload.find({ collection: 'parish', limit: 100 })
const results = await Promise.all(
parishes.docs.map(async (parish) => {
const doc = await fetchLastAnnouncement(parish.id)
return doc ? { parish, doc } : null
}),
)
const results = await Promise.all(
parishes.docs.map(async (parish) => {
const doc = await fetchLastAnnouncement(parish.id)
return doc ? { parish, doc } : null
}),
)
return results.filter(
(r): r is { parish: Parish; doc: Announcement } => !!r,
)
}
return results.filter(
(r): r is { parish: Parish; doc: Announcement } => !!r,
)
},
['fetchLastAnnouncements'],
{ revalidate: CACHE_TTL },
)

View file

@ -1,7 +1,10 @@
import { getPayload } from 'payload'
import { unstable_cache } from 'next/cache'
import config from '@/payload.config'
import { Calendar, Parish } from '@/payload-types'
const CACHE_TTL = 300 // 5 minutes
/**
* Fetch last calendar for a parish
*/
@ -45,20 +48,22 @@ export const fetchLastCalendar = async (
/**
* Fetch the last calendar for each parish
*/
export const fetchLastCalendars = async (): Promise<
Array<{ parish: Parish; doc: Calendar }>
> => {
const payload = await getPayload({ config })
const parishes = await payload.find({ collection: 'parish', limit: 100 })
export const fetchLastCalendars = unstable_cache(
async (): Promise<Array<{ parish: Parish; doc: Calendar }>> => {
const payload = await getPayload({ config })
const parishes = await payload.find({ collection: 'parish', limit: 100 })
const results = await Promise.all(
parishes.docs.map(async (parish) => {
const doc = await fetchLastCalendar(parish.id)
return doc ? { parish, doc } : null
}),
)
const results = await Promise.all(
parishes.docs.map(async (parish) => {
const doc = await fetchLastCalendar(parish.id)
return doc ? { parish, doc } : null
}),
)
return results.filter(
(r): r is { parish: Parish; doc: Calendar } => !!r,
)
}
return results.filter(
(r): r is { parish: Parish; doc: Calendar } => !!r,
)
},
['fetchLastCalendars'],
{ revalidate: CACHE_TTL },
)

View file

@ -1,13 +1,79 @@
import { getPayload, PaginatedDocs } from 'payload'
import { unstable_cache } from 'next/cache'
import config from '@/payload.config'
import { Worship } from '@/payload-types'
const CACHE_TTL = 300 // 5 minutes
type FetchWorshipArgs = {
fromDate?: Date
tillDate?: Date
locations?: string[]
}
// Resolved args use ISO strings so they serialize into a stable cache key.
type ResolvedWorshipArgs = {
fromDate: string
tillDate?: string
locations?: string[]
}
// Round down to the cache window so millisecond-precision dates produce a
// stable key for the duration of the TTL.
function roundDownToTtl(date: Date): Date {
const ms = CACHE_TTL * 1000
return new Date(Math.floor(date.getTime() / ms) * ms)
}
const getWorship = unstable_cache(
async (args: ResolvedWorshipArgs): Promise<PaginatedDocs<Worship>> => {
const { fromDate, tillDate, locations } = args
const query: any = {
and: [
{
date: {
greater_than_equal: fromDate,
},
},
],
}
if (tillDate) {
query.and.push({
date: {
less_than: tillDate,
},
})
}
if (locations) {
query.and.push({
location: {
in: locations,
},
})
}
const payload = await getPayload({ config })
return payload.find({
collection: 'worship',
sort: 'date',
where: query,
select: {
type: true,
date: true,
cancelled: true,
location: true,
title: true,
},
limit: 100,
}) as Promise<PaginatedDocs<Worship>>
},
['fetchWorship'],
{ revalidate: CACHE_TTL },
)
export const fetchWorship = async (
args?: FetchWorshipArgs,
): Promise<PaginatedDocs<Worship>> => {
@ -19,46 +85,11 @@ export const fetchWorship = async (
date.setHours(0, 0, 0, 0)
}
const query: any = {
and: [
{
date: {
greater_than_equal: date.toISOString(),
},
},
],
}
if (tillDate) {
query.and.push({
date: {
less_than: tillDate.toISOString(),
},
})
}
if (locations) {
query.and.push({
location: {
in: locations,
},
})
}
const payload = await getPayload({ config })
return payload.find({
collection: 'worship',
sort: 'date',
where: query,
select: {
type: true,
date: true,
cancelled: true,
location: true,
title: true,
},
limit: 100,
}) as Promise<PaginatedDocs<Worship>>
return getWorship({
fromDate: roundDownToTtl(date).toISOString(),
tillDate: tillDate ? roundDownToTtl(tillDate).toISOString() : undefined,
locations,
})
}
/**