Start actively managing blob cache

This commit is contained in:
Sam Becker 2023-09-23 00:46:12 -05:00
parent 459785ceeb
commit 061d3bb03b
4 changed files with 47 additions and 14 deletions

View File

@ -12,15 +12,16 @@ import {
} from '@/photo/actions';
import { FaRegEdit } from 'react-icons/fa';
import SubmitButtonWithStatus from '@/components/SubmitButtonWithStatus';
import {
pathForBlobUrl,
getBlobPhotoUrls,
getBlobUploadUrls,
} from '@/services/blob';
import { pathForBlobUrl } from '@/services/blob';
import { pathForPhoto, pathForPhotoEdit } from '@/site/paths';
import { getPhotosLimitForQuery, titleForPhoto } from '@/photo';
import MorePhotos from '@/components/MorePhotos';
import { getPhotosCached, getPhotosCountCached } from '@/cache';
import {
getBlobPhotoUrlsCached,
getBlobUploadUrlsCached,
getPhotosCached,
getPhotosCountCached,
} from '@/cache';
export const runtime = 'edge';
@ -41,8 +42,8 @@ export default async function AdminPage({
] = await Promise.all([
getPhotosCached({ sortBy: 'createdAt', limit }),
getPhotosCountCached(),
getBlobUploadUrls(),
DEBUG_PHOTO_BLOBS ? getBlobPhotoUrls() : [],
getBlobUploadUrlsCached(),
DEBUG_PHOTO_BLOBS ? getBlobPhotoUrlsCached() : [],
]);
const showMorePhotos = count > photos.length;

View File

@ -1,9 +1,9 @@
import { revalidatePhotosAndBlobTag } from '@/cache';
import {
ACCEPTED_PHOTO_FILE_TYPES,
isUploadPathnameValid,
} from '@/services/blob';
import { handleUpload, type HandleUploadBody } from '@vercel/blob/client';
import { revalidatePath } from 'next/cache';
import { NextResponse } from 'next/server';
export const runtime = 'edge';
@ -25,12 +25,15 @@ export async function POST(request: Request): Promise<NextResponse> {
throw new Error('Invalid upload');
}
},
// This argument is required, but doesn't seem to fire
onUploadCompleted: async () => {
revalidatePath('admin/photos');
revalidatePhotosAndBlobTag();
},
});
revalidatePhotosAndBlobTag();
return NextResponse.json(jsonResponse);
} catch (error) {
revalidatePhotosAndBlobTag();
return NextResponse.json(
{ error: (error as Error).message },
{ status: 400 },

26
src/cache/index.ts vendored
View File

@ -8,10 +8,12 @@ import {
getUniqueTags,
} from '@/services/postgres';
import { parseCachedPhotosDates, parseCachedPhotoDates } from '@/photo';
import { getBlobPhotoUrls, getBlobUploadUrls } from '@/services/blob';
const TAG_PHOTOS = 'photos';
const TAG_PHOTOS_COUNT = 'photos-count';
const TAG_TAGS = 'tags';
const TAG_BLOB = 'blob';
const getPhotosCacheTags = (options: GetPhotosOptions = {}) => {
const tags = [];
@ -42,6 +44,14 @@ const getPhotoCacheTag = (photoId: string) => `photo-${photoId}`;
export const revalidatePhotosTag = () =>
revalidateTag(TAG_PHOTOS);
export const revalidateBlobTag = () =>
revalidateTag(TAG_BLOB);
export const revalidatePhotosAndBlobTag = () => {
revalidateTag(TAG_PHOTOS);
revalidateTag(TAG_BLOB);
};
export const getPhotosCached: typeof getPhotos = (...args) =>
unstable_cache(
() => getPhotos(...args),
@ -74,6 +84,22 @@ export const getUniqueTagsCached: typeof getUniqueTags = (...args) =>
}
)();
export const getBlobUploadUrlsCached: typeof getBlobUploadUrls = (...args) =>
unstable_cache(
() => getBlobUploadUrls(...args),
[TAG_BLOB], {
tags: [TAG_BLOB],
}
)();
export const getBlobPhotoUrlsCached: typeof getBlobPhotoUrls = (...args) =>
unstable_cache(
() => getBlobPhotoUrls(...args),
[TAG_BLOB], {
tags: [TAG_BLOB],
}
)();
export const getImageCacheHeadersForAuth = (session?: Session) => {
return {
'Cache-Control': !session?.user

View File

@ -1,6 +1,5 @@
'use server';
import { revalidatePath } from 'next/cache';
import {
sqlDeletePhoto,
sqlInsertPhoto,
@ -12,7 +11,11 @@ import {
convertUploadToPhoto,
deleteBlobPhoto,
} from '@/services/blob';
import { revalidatePhotosTag } from '@/cache';
import {
revalidateBlobTag,
revalidatePhotosAndBlobTag,
revalidatePhotosTag,
} from '@/cache';
export async function createPhotoAction(formData: FormData) {
const photo = convertFormDataToPhoto(formData, true);
@ -26,7 +29,7 @@ export async function createPhotoAction(formData: FormData) {
await sqlInsertPhoto(photo);
revalidatePhotosTag();
revalidatePhotosAndBlobTag();
redirect('/admin/photos');
}
@ -53,5 +56,5 @@ export async function deletePhotoAction(formData: FormData) {
export async function deleteBlobPhotoAction(formData: FormData) {
await deleteBlobPhoto(formData.get('url') as string);
revalidatePath('/admin/photos');
revalidateBlobTag();
};