Increase cache coverage

This commit is contained in:
Sam Becker 2025-11-15 17:03:32 -06:00
parent 62308b26a6
commit c5c78e527e
9 changed files with 102 additions and 72 deletions

View File

@ -1,12 +1,14 @@
import { redirect } from 'next/navigation'; import { redirect } from 'next/navigation';
import { import {
getAlbumsWithMetaCached,
getAlbumTitlesForPhotoCached,
getPhotoNoStore, getPhotoNoStore,
getUniqueFilmsCached, getUniqueFilmsCached,
getUniqueRecipesCached, getUniqueRecipesCached,
getUniqueTagsCached, getUniqueTagsCached,
} from '@/photo/cache'; } from '@/photo/cache';
import {
getAlbumTitlesForPhotoCached,
getAlbumsWithMetaCached,
} from '@/album/cache';
import { PATH_ADMIN } from '@/app/path'; import { PATH_ADMIN } from '@/app/path';
import PhotoEditPageClient from '@/photo/PhotoEditPageClient'; import PhotoEditPageClient from '@/photo/PhotoEditPageClient';
import { import {

View File

@ -1,6 +1,7 @@
import { getStorageUploadUrlsNoStore } from '@/platforms/storage/cache'; import { getStorageUploadUrlsNoStore } from '@/platforms/storage/cache';
import AppGrid from '@/components/AppGrid'; import AppGrid from '@/components/AppGrid';
import { getUniqueTagsCached, getAlbumsWithMetaCached } from '@/photo/cache'; import { getUniqueTagsCached } from '@/photo/cache';
import { getAlbumsWithMetaCached } from '@/album/cache';
import AdminUploadsClient from '@/admin/AdminUploadsClient'; import AdminUploadsClient from '@/admin/AdminUploadsClient';
import { redirect } from 'next/navigation'; import { redirect } from 'next/navigation';
import { PATH_ADMIN_PHOTOS } from '@/app/path'; import { PATH_ADMIN_PHOTOS } from '@/app/path';

View File

@ -1,5 +1,4 @@
import { INFINITE_SCROLL_GRID_INITIAL } from '@/photo'; import { INFINITE_SCROLL_GRID_INITIAL } from '@/photo';
import { getPhotos } from '@/photo/query';
import { PATH_ROOT } from '@/app/path'; import { PATH_ROOT } from '@/app/path';
import type { Metadata } from 'next'; import type { Metadata } from 'next';
import { redirect } from 'next/navigation'; import { redirect } from 'next/navigation';
@ -7,13 +6,14 @@ import { cache } from 'react';
import { staticallyGenerateCategoryIfConfigured } from '@/app/static'; import { staticallyGenerateCategoryIfConfigured } from '@/app/static';
import { getAppText } from '@/i18n/state/server'; import { getAppText } from '@/i18n/state/server';
import AlbumOverview from '@/album/AlbumOverview'; import AlbumOverview from '@/album/AlbumOverview';
import {
getAlbumFromSlug,
getAlbumsWithMeta,
getTagsForAlbum,
} from '@/album/query';
import { Album, generateMetaForAlbum } from '@/album'; import { Album, generateMetaForAlbum } from '@/album';
import { getPhotosAlbumDataCached } from '@/album/data'; import { getPhotosAlbumDataCached } from '@/album/data';
import {
getAlbumFromSlugCached,
getAlbumsWithMetaCached,
getTagsForAlbumCached,
} from '@/album/cache';
import { getPhotosCached } from '@/photo/cache';
const getPhotosAlbumDataCachedCached = cache((album: Album) => const getPhotosAlbumDataCachedCached = cache((album: Album) =>
getPhotosAlbumDataCached({ album, limit: INFINITE_SCROLL_GRID_INITIAL})); getPhotosAlbumDataCached({ album, limit: INFINITE_SCROLL_GRID_INITIAL}));
@ -21,7 +21,7 @@ const getPhotosAlbumDataCachedCached = cache((album: Album) =>
export const generateStaticParams = staticallyGenerateCategoryIfConfigured( export const generateStaticParams = staticallyGenerateCategoryIfConfigured(
'albums', 'albums',
'page', 'page',
getAlbumsWithMeta, getAlbumsWithMetaCached,
albums => albums.map(({ album }) => ({ album: album.slug })), albums => albums.map(({ album }) => ({ album: album.slug })),
); );
@ -36,7 +36,7 @@ export async function generateMetadata({
const albumSlug = decodeURIComponent(albumFromParams); const albumSlug = decodeURIComponent(albumFromParams);
const album = await getAlbumFromSlug(albumSlug); const album = await getAlbumFromSlugCached(albumSlug);
if (!album) { return {}; } if (!album) { return {}; }
@ -80,13 +80,13 @@ export default async function AlbumPage({
const albumSlug = decodeURIComponent(albumFromParams); const albumSlug = decodeURIComponent(albumFromParams);
const album = await getAlbumFromSlug(albumSlug); const album = await getAlbumFromSlugCached(albumSlug);
if (!album) { redirect(PATH_ROOT); } if (!album) { redirect(PATH_ROOT); }
const photos = await getPhotos({ album }); const photos = await getPhotosCached({ album });
const tags = await getTagsForAlbum(album.id); const tags = await getTagsForAlbumCached(album.id);
return ( return (
<AlbumOverview {...{ <AlbumOverview {...{

View File

@ -4,8 +4,8 @@ import {
getPhotosMostRecentUpdateCached, getPhotosMostRecentUpdateCached,
getUniqueRecipesCached, getUniqueRecipesCached,
getUniqueTagsCached, getUniqueTagsCached,
getAlbumsWithMetaCached,
} from '@/photo/cache'; } from '@/photo/cache';
import { getAlbumsWithMetaCached } from '@/album/cache';
import { import {
PATH_ADMIN_ALBUMS, PATH_ADMIN_ALBUMS,
PATH_ADMIN_PHOTOS, PATH_ADMIN_PHOTOS,

View File

@ -8,17 +8,17 @@ import { testStorageConnection } from '@/platforms/storage';
import { testGooglePlacesConnection } from '@/platforms/google-places'; import { testGooglePlacesConnection } from '@/platforms/google-places';
import { APP_CONFIGURATION } from '@/app/config'; import { APP_CONFIGURATION } from '@/app/config';
import { getStorageUploadUrlsNoStore } from '@/platforms/storage/cache'; import { getStorageUploadUrlsNoStore } from '@/platforms/storage/cache';
import {
getPhotosMeta,
getUniqueTags,
getUniqueRecipes,
getPhotosInNeedOfUpdateCount,
} from '@/photo/query';
import { import {
getGitHubMetaForCurrentApp, getGitHubMetaForCurrentApp,
indicatorStatusForSignificantInsights, indicatorStatusForSignificantInsights,
} from './insights'; } from './insights';
import { getAlbumsWithMeta } from '@/album/query'; import {
getPhotosInNeedOfUpdateCountCached,
getPhotosMetaCached,
getUniqueRecipesCached,
getUniqueTagsCached,
} from '@/photo/cache';
import { getAlbumsWithMetaCached } from '@/album/cache';
export type AdminData = Awaited<ReturnType<typeof getAdminDataAction>>; export type AdminData = Awaited<ReturnType<typeof getAdminDataAction>>;
@ -34,13 +34,13 @@ export const getAdminDataAction = async () =>
tagsCount, tagsCount,
recipesCount, recipesCount,
] = await Promise.all([ ] = await Promise.all([
getPhotosMeta() getPhotosMetaCached()
.then(({ count }) => count) .then(({ count }) => count)
.catch(() => 0), .catch(() => 0),
getPhotosMeta({ hidden: 'only' }) getPhotosMetaCached({ hidden: 'only' })
.then(({ count }) => count) .then(({ count }) => count)
.catch(() => 0), .catch(() => 0),
getPhotosInNeedOfUpdateCount(), getPhotosInNeedOfUpdateCountCached(),
getGitHubMetaForCurrentApp(), getGitHubMetaForCurrentApp(),
getStorageUploadUrlsNoStore() getStorageUploadUrlsNoStore()
.then(urls => urls.length) .then(urls => urls.length)
@ -48,13 +48,13 @@ export const getAdminDataAction = async () =>
console.error(`Error getting blob upload urls: ${e}`); console.error(`Error getting blob upload urls: ${e}`);
return 0; return 0;
}), }),
getAlbumsWithMeta() getAlbumsWithMetaCached()
.then(albums => albums.length) .then(albums => albums.length)
.catch(() => 0), .catch(() => 0),
getUniqueTags() getUniqueTagsCached()
.then(tags => tags.length) .then(tags => tags.length)
.catch(() => 0), .catch(() => 0),
getUniqueRecipes() getUniqueRecipesCached()
.then(recipes => recipes.length) .then(recipes => recipes.length)
.catch(() => 0), .catch(() => 0),
]); ]);

View File

@ -1,4 +1,5 @@
import { getAlbumsWithMetaCached, getUniqueTagsCached } from '@/photo/cache'; import { getUniqueTagsCached } from '@/photo/cache';
import { getAlbumsWithMetaCached } from '@/album/cache';
import AdminBatchEditPanelClient from './AdminBatchEditPanelClient'; import AdminBatchEditPanelClient from './AdminBatchEditPanelClient';
export default async function AdminBatchEditPanel({ export default async function AdminBatchEditPanel({

32
src/album/cache.ts Normal file
View File

@ -0,0 +1,32 @@
import {
getAlbumFromSlug,
getAlbumsWithMeta,
getAlbumTitlesForPhoto,
getTagsForAlbum,
} from '@/album/query';
import { KEY_ALBUMS, KEY_PHOTOS } from '@/photo/cache';
import { unstable_cache } from 'next/cache';
export const getAlbumFromSlugCached =
unstable_cache(
getAlbumFromSlug,
[KEY_PHOTOS, KEY_ALBUMS],
);
export const getAlbumTitlesForPhotoCached =
unstable_cache(
getAlbumTitlesForPhoto,
[KEY_PHOTOS, KEY_ALBUMS],
);
export const getAlbumsWithMetaCached =
unstable_cache(
getAlbumsWithMeta,
[KEY_PHOTOS, KEY_ALBUMS],
);
export const getTagsForAlbumCached =
unstable_cache(
getTagsForAlbum,
[KEY_PHOTOS, KEY_ALBUMS],
);

View File

@ -1,13 +1,3 @@
import {
getPhotosMeta,
getUniqueCameras,
getUniqueFilms,
getUniqueFocalLengths,
getUniqueLenses,
getUniqueRecipes,
getUniqueTags,
getUniqueYears,
} from '@/photo/query';
import { import {
SHOW_FILMS, SHOW_FILMS,
SHOW_FOCAL_LENGTHS, SHOW_FOCAL_LENGTHS,
@ -23,7 +13,17 @@ import { createLensKey } from '@/lens';
import { sortTagsByCount } from '@/tag'; import { sortTagsByCount } from '@/tag';
import { sortCategoriesByCount } from '@/category'; import { sortCategoriesByCount } from '@/category';
import { sortFocalLengths } from '@/focal'; import { sortFocalLengths } from '@/focal';
import { getAlbumsWithMeta } from '@/album/query'; import {
getPhotosMetaCached,
getUniqueCamerasCached,
getUniqueFilmsCached,
getUniqueFocalLengthsCached,
getUniqueLensesCached,
getUniqueRecipesCached,
getUniqueTagsCached,
getUniqueYearsCached,
} from '@/photo/cache';
import { getAlbumsWithMetaCached } from '@/album/cache';
type CategoryData = Awaited<ReturnType<typeof getDataForCategories>>; type CategoryData = Awaited<ReturnType<typeof getDataForCategories>>;
@ -41,7 +41,7 @@ export const NULL_CATEGORY_DATA: CategoryData = {
export const getDataForCategories = () => Promise.all([ export const getDataForCategories = () => Promise.all([
SHOW_RECENTS SHOW_RECENTS
? getPhotosMeta({ recent: true }) ? getPhotosMetaCached({ recent: true })
.then(({ count, dateRange }) => count && dateRange .then(({ count, dateRange }) => count && dateRange
? [{ ? [{
count, count,
@ -50,41 +50,41 @@ export const getDataForCategories = () => Promise.all([
.catch(() => []) .catch(() => [])
: undefined, : undefined,
SHOW_YEARS SHOW_YEARS
? getUniqueYears() ? getUniqueYearsCached()
.catch(() => []) .catch(() => [])
: undefined, : undefined,
SHOW_CAMERAS SHOW_CAMERAS
? getUniqueCameras() ? getUniqueCamerasCached()
.then(sortCategoriesByCount) .then(sortCategoriesByCount)
.catch(() => []) .catch(() => [])
: undefined, : undefined,
SHOW_LENSES SHOW_LENSES
? getUniqueLenses() ? getUniqueLensesCached()
.then(sortCategoriesByCount) .then(sortCategoriesByCount)
.catch(() => []) .catch(() => [])
: undefined, : undefined,
SHOW_TAGS SHOW_TAGS
? getUniqueTags() ? getUniqueTagsCached()
.then(sortTagsByCount) .then(sortTagsByCount)
.catch(() => []) .catch(() => [])
: undefined, : undefined,
SHOW_RECIPES SHOW_RECIPES
? getUniqueRecipes() ? getUniqueRecipesCached()
.then(sortCategoriesByCount) .then(sortCategoriesByCount)
.catch(() => []) .catch(() => [])
: undefined, : undefined,
SHOW_FILMS SHOW_FILMS
? getUniqueFilms() ? getUniqueFilmsCached()
.then(sortCategoriesByCount) .then(sortCategoriesByCount)
.catch(() => []) .catch(() => [])
: undefined, : undefined,
SHOW_FOCAL_LENGTHS SHOW_FOCAL_LENGTHS
? getUniqueFocalLengths() ? getUniqueFocalLengthsCached()
.then(sortFocalLengths) .then(sortFocalLengths)
.catch(() => []) .catch(() => [])
: undefined, : undefined,
SHOW_ALBUMS SHOW_ALBUMS
? getAlbumsWithMeta() ? getAlbumsWithMetaCached()
.catch(() => []) .catch(() => [])
: undefined, : undefined,
]).then(([ ]).then(([

View File

@ -17,6 +17,7 @@ import {
getUniqueLenses, getUniqueLenses,
getUniqueRecipes, getUniqueRecipes,
getUniqueYears, getUniqueYears,
getPhotosInNeedOfUpdateCount,
} from '@/photo/query'; } from '@/photo/query';
import { PhotoQueryOptions } from '@/db'; import { PhotoQueryOptions } from '@/db';
import { parseCachedPhotoDates, parseCachedPhotosDates } from '@/photo'; import { parseCachedPhotoDates, parseCachedPhotosDates } from '@/photo';
@ -39,23 +40,22 @@ import {
PREFIX_ALBUM, PREFIX_ALBUM,
} from '@/app/path'; } from '@/app/path';
import { createLensKey } from '@/lens'; import { createLensKey } from '@/lens';
import { getAlbumsWithMeta, getAlbumTitlesForPhoto } from '@/album/query';
// Table key // Table key
export const KEY_PHOTOS = 'photos'; export const KEY_PHOTOS = 'photos';
const KEY_PHOTO = 'photo'; export const KEY_PHOTO = 'photo';
// Field keys // Field keys
const KEY_CAMERAS = 'cameras'; export const KEY_CAMERAS = 'cameras';
const KEY_LENSES = 'lenses'; export const KEY_LENSES = 'lenses';
const KEY_ALBUMS = 'albums'; export const KEY_ALBUMS = 'albums';
const KEY_TAGS = 'tags'; export const KEY_TAGS = 'tags';
const KEY_FILMS = 'films'; export const KEY_FILMS = 'films';
const KEY_RECIPES = 'recipes'; export const KEY_RECIPES = 'recipes';
const KEY_FOCAL_LENGTHS = 'focal-lengths'; export const KEY_FOCAL_LENGTHS = 'focal-lengths';
const KEY_YEARS = 'years'; export const KEY_YEARS = 'years';
// Type keys // Type keys
const KEY_COUNT = 'count'; export const KEY_COUNT = 'count';
const KEY_DATE_RANGE = 'date-range'; export const KEY_DATE_RANGE = 'date-range';
const getCacheKeyForPhotoQueryOptions = ( const getCacheKeyForPhotoQueryOptions = (
options: PhotoQueryOptions, options: PhotoQueryOptions,
@ -73,7 +73,7 @@ const getCacheKeyForPhotoQueryOptions = (
} }
case 'album': { case 'album': {
const album = options[option]; const album = options[option];
return album ? album.slug : null; return album?.id ? `${option}-${album.id}` : null;
} }
case 'takenBefore': case 'takenBefore':
case 'takenAfterInclusive': case 'takenAfterInclusive':
@ -225,16 +225,10 @@ export const getPhotoCached = (...args: Parameters<typeof getPhoto>) =>
[KEY_PHOTOS, KEY_PHOTO], [KEY_PHOTOS, KEY_PHOTO],
)(...args).then(photo => photo ? parseCachedPhotoDates(photo) : undefined); )(...args).then(photo => photo ? parseCachedPhotoDates(photo) : undefined);
export const getAlbumTitlesForPhotoCached = export const getPhotosInNeedOfUpdateCountCached =
unstable_cache( unstable_cache(
getAlbumTitlesForPhoto, getPhotosInNeedOfUpdateCount,
[KEY_PHOTOS, KEY_ALBUMS], [KEY_PHOTOS, KEY_COUNT],
);
export const getAlbumsWithMetaCached =
unstable_cache(
getAlbumsWithMeta,
[KEY_PHOTOS, KEY_ALBUMS],
); );
export const getUniqueTagsCached = export const getUniqueTagsCached =