Make syncing/updating photos more resilient to timeouts
This commit is contained in:
parent
791d020c94
commit
930b80b9f1
@ -17,6 +17,8 @@ import { getPhotoIds } from '@/photo/db/query';
|
||||
import { GENERATE_STATIC_PARAMS_LIMIT } from '@/photo/db';
|
||||
import { ReactNode, cache } from 'react';
|
||||
|
||||
export const maxDuration = 60;
|
||||
|
||||
const getPhotosNearIdCachedCached = cache((photoId: string) =>
|
||||
getPhotosNearIdCached(photoId, { limit: RELATED_GRID_PHOTOS_TO_SHOW + 2 }));
|
||||
|
||||
|
||||
@ -11,6 +11,7 @@ import { getPhotos, getPhotosMeta } from '@/photo/db/query';
|
||||
import PhotosLargeInfinite from '@/photo/PhotosLargeInfinite';
|
||||
|
||||
export const dynamic = 'force-static';
|
||||
export const maxDuration = 60;
|
||||
|
||||
const getPhotosCached = cache(() => getPhotos({
|
||||
limit: INFINITE_SCROLL_LARGE_PHOTO_INITIAL,
|
||||
|
||||
@ -56,10 +56,10 @@ export const createPhotoAction = async (formData: FormData) =>
|
||||
|
||||
const photo = convertFormDataToPhotoDbInsert(formData);
|
||||
|
||||
const updatedUrl = await convertUploadToPhoto(
|
||||
photo.url,
|
||||
const updatedUrl = await convertUploadToPhoto({
|
||||
urlOrigin: photo.url,
|
||||
shouldStripGpsData,
|
||||
);
|
||||
});
|
||||
|
||||
if (updatedUrl) {
|
||||
photo.url = updatedUrl;
|
||||
@ -141,11 +141,11 @@ export const addAllUploadsAction = async ({
|
||||
addedUploadUrls: addedUploadUrls.join(','),
|
||||
});
|
||||
|
||||
const updatedUrl = await convertUploadToPhoto(
|
||||
url,
|
||||
shouldStripGpsData,
|
||||
const updatedUrl = await convertUploadToPhoto({
|
||||
urlOrigin: url,
|
||||
fileBytes,
|
||||
);
|
||||
shouldStripGpsData,
|
||||
});
|
||||
if (updatedUrl) {
|
||||
const subhead = 'Adding to database';
|
||||
stream.update({
|
||||
@ -179,16 +179,25 @@ export const updatePhotoAction = async (formData: FormData) =>
|
||||
runAuthenticatedAdminServerAction(async () => {
|
||||
const photo = convertFormDataToPhotoDbInsert(formData);
|
||||
|
||||
let url: string | undefined;
|
||||
let urlToDelete: string | undefined;
|
||||
if (photo.hidden && photo.url.includes(photo.id)) {
|
||||
// Backfill:
|
||||
// Anonymize storage url on update if necessary by
|
||||
// re-running image upload transfer logic
|
||||
url = await convertUploadToPhoto(photo.url);
|
||||
if (url) { photo.url = url; }
|
||||
const url = await convertUploadToPhoto({
|
||||
urlOrigin: photo.url,
|
||||
shouldDeleteOrigin: false,
|
||||
});
|
||||
if (url) {
|
||||
urlToDelete = photo.url;
|
||||
photo.url = url;
|
||||
}
|
||||
}
|
||||
|
||||
await updatePhoto(photo);
|
||||
await updatePhoto(photo)
|
||||
.then(async () => {
|
||||
if (urlToDelete) { await deleteFile(urlToDelete); }
|
||||
});
|
||||
|
||||
revalidatePhoto(photo.id);
|
||||
|
||||
@ -307,16 +316,21 @@ export const syncPhotoAction = async (photoId: string) =>
|
||||
generateResizedImage: AI_TEXT_GENERATION_ENABLED,
|
||||
});
|
||||
|
||||
let urlToDelete: string | undefined;
|
||||
if (photoFormExif) {
|
||||
if (photo.url.includes(photo.id) || shouldStripGpsData) {
|
||||
// Anonymize storage url on update if necessary by
|
||||
// re-running image upload transfer logic
|
||||
const url = await convertUploadToPhoto(
|
||||
photo.url,
|
||||
shouldStripGpsData,
|
||||
const url = await convertUploadToPhoto({
|
||||
urlOrigin: photo.url,
|
||||
fileBytes,
|
||||
);
|
||||
if (url) { photo.url = url; }
|
||||
shouldStripGpsData,
|
||||
shouldDeleteOrigin: false,
|
||||
});
|
||||
if (url) {
|
||||
urlToDelete = photo.url;
|
||||
photo.url = url;
|
||||
}
|
||||
}
|
||||
|
||||
const {
|
||||
@ -340,7 +354,11 @@ export const syncPhotoAction = async (photoId: string) =>
|
||||
{ semanticDescription: aiSemanticDescription },
|
||||
});
|
||||
|
||||
await updatePhoto(photoFormDbInsert);
|
||||
await updatePhoto(photoFormDbInsert)
|
||||
.then(async () => {
|
||||
if (urlToDelete) { await deleteFile(urlToDelete); }
|
||||
});
|
||||
|
||||
revalidateAllKeysAndPaths();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import {
|
||||
copyFile,
|
||||
deleteFile,
|
||||
generateRandomFileNameForPhoto,
|
||||
getExtensionFromStorageUrl,
|
||||
@ -7,24 +8,32 @@ import {
|
||||
} from '@/services/storage';
|
||||
import { removeGpsData } from './server';
|
||||
|
||||
export const convertUploadToPhoto = async (
|
||||
urlOrigin: string,
|
||||
stripGps?: boolean,
|
||||
fileBytes?: ArrayBuffer,
|
||||
) => {
|
||||
export const convertUploadToPhoto = async ({
|
||||
urlOrigin,
|
||||
fileBytes,
|
||||
shouldStripGpsData,
|
||||
shouldDeleteOrigin = true,
|
||||
} : {
|
||||
urlOrigin: string
|
||||
fileBytes?: ArrayBuffer
|
||||
shouldStripGpsData?: boolean
|
||||
shouldDeleteOrigin?: boolean
|
||||
}) => {
|
||||
const fileName = generateRandomFileNameForPhoto();
|
||||
const fileExtension = getExtensionFromStorageUrl(urlOrigin);
|
||||
const photoPath = `${fileName}.${fileExtension || 'jpg'}`;
|
||||
if (stripGps) {
|
||||
if (shouldStripGpsData) {
|
||||
const fileWithoutGps = await removeGpsData(
|
||||
fileBytes ?? await fetch(urlOrigin, { cache: 'no-store' })
|
||||
.then(res => res.arrayBuffer())
|
||||
);
|
||||
return putFile(fileWithoutGps, photoPath).then(async url => {
|
||||
if (url) { await deleteFile(urlOrigin); }
|
||||
if (url && shouldDeleteOrigin) { await deleteFile(urlOrigin); }
|
||||
return url;
|
||||
});
|
||||
} else {
|
||||
return moveFile(urlOrigin, photoPath);
|
||||
return shouldDeleteOrigin
|
||||
? moveFile(urlOrigin, photoPath)
|
||||
: copyFile(urlOrigin, photoPath);
|
||||
}
|
||||
};
|
||||
|
||||
Loading…
Reference in New Issue
Block a user