Start actively managing blob cache
This commit is contained in:
parent
459785ceeb
commit
061d3bb03b
@ -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;
|
||||
|
||||
@ -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
26
src/cache/index.ts
vendored
@ -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
|
||||
|
||||
@ -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();
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user