Skip to content

Commit

Permalink
feat(store): only let image transformations fail on Sharp errors
Browse files Browse the repository at this point in the history
  • Loading branch information
dirkdev98 committed Aug 30, 2023
1 parent 9868dc3 commit 945136d
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 69 deletions.
2 changes: 1 addition & 1 deletion packages/store/src/file.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ export async function fileCreateOrUpdate(
* @returns {Promise<Buffer>}
*/
async function fileTransformInPlaceInternal(fileBuffer, operations) {
const sharpInstance = sharp(fileBuffer);
const sharpInstance = sharp(fileBuffer, { failOn: "error" });

if (operations.stripMetadata !== true) {
sharpInstance.withMetadata({});
Expand Down
124 changes: 56 additions & 68 deletions packages/store/src/files-jobs.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ export function jobFileGeneratePlaceholderImage(s3Client, bucketName) {
return;
}

const sharpInstance = sharp(buffer).rotate();
const sharpInstance = sharp(buffer, { failOn: "error" }).rotate();
const metadata = await sharpInstance.metadata();

const placeholderImageBuffer = await sharpInstance
Expand Down Expand Up @@ -196,82 +196,70 @@ export function jobFileTransformImage(s3Client) {
return;
}

try {
const sharpInstance = sharp(buffer);
sharpInstance.rotate();

const metadataPromise = sharpInstance.metadata();

const originalWidth =
file.meta?.originalWidth ?? (await metadataPromise).width;
const originalHeight =
file.meta?.originalHeight ?? (await metadataPromise).height;

if (!isNil(originalWidth) && originalWidth > options.w) {
// Only resize if width is greater than the needed with, so we don't upscale
sharpInstance.resize(options.w);
}

if (options.contentType === "image/webp") {
sharpInstance.webp({ quality: options.q });
} else if (options.contentType === "image/avif") {
sharpInstance.avif({ quality: options.q });
} else if (options.contentType === "image/png") {
sharpInstance.png({ quality: options.q });
} else if (
options.contentType === "image/jpg" ||
options.contentType === "image/jpeg"
) {
sharpInstance.jpeg({ quality: options.q });
} else if (options.contentType === "image/gif") {
sharpInstance.gif({});
}

const image = await fileCreateOrUpdate(
sql,
s3Client,
{
// @ts-expect-error
bucketName: file.bucketName,
},
{
name: transformKey,
contentType: options.contentType,
meta: {
transformedFromOriginal: file.id,
},
const sharpInstance = sharp(buffer, { failOn: "error" });
sharpInstance.rotate();

const metadataPromise = sharpInstance.metadata();

const originalWidth =
file.meta?.originalWidth ?? (await metadataPromise).width;
const originalHeight =
file.meta?.originalHeight ?? (await metadataPromise).height;

if (!isNil(originalWidth) && originalWidth > options.w) {
// Only resize if width is greater than the needed with, so we don't upscale
sharpInstance.resize(options.w);
}

if (options.contentType === "image/webp") {
sharpInstance.webp({ quality: options.q });
} else if (options.contentType === "image/avif") {
sharpInstance.avif({ quality: options.q });
} else if (options.contentType === "image/png") {
sharpInstance.png({ quality: options.q });
} else if (
options.contentType === "image/jpg" ||
options.contentType === "image/jpeg"
) {
sharpInstance.jpeg({ quality: options.q });
} else if (options.contentType === "image/gif") {
sharpInstance.gif({});
}

const image = await fileCreateOrUpdate(
sql,
s3Client,
{
// @ts-expect-error
bucketName: file.bucketName,
},
{
name: transformKey,
contentType: options.contentType,
meta: {
transformedFromOriginal: file.id,
},
await sharpInstance.toBuffer(),
);
},
await sharpInstance.toBuffer(),
);

// @ts-expect-error
await atomicSetTransformKey(sql, file.id, transformKey, image.id);

if (
(isNil(file.meta?.originalWidth) || isNil(file.meta?.originalHeight)) &&
!isNil(originalWidth) &&
!isNil(originalHeight)
) {
// Update the original image to include the width and height.
await query`UPDATE "file"
// @ts-expect-error
await atomicSetTransformKey(sql, file.id, transformKey, image.id);

if (
(isNil(file.meta?.originalWidth) || isNil(file.meta?.originalHeight)) &&
!isNil(originalWidth) &&
!isNil(originalHeight)
) {
// Update the original image to include the width and height.
await query`UPDATE "file"
SET
"meta" = jsonb_set(jsonb_set("meta", '{originalHeight}', ${String(
originalHeight,
)}::jsonb), '{originalWidth}',
${String(originalWidth)}::jsonb)
WHERE
id = ${file.id}`.exec(sql);
}
} catch (/** @type {any} */ e) {
if (
e.message === "VipsJpeg: Invalid SOS parameters for sequential JPEG"
) {
// JPEG error, just return the original image and never try again.
// @ts-expect-error
await atomicSetTransformKey(sql, file.id, transformKey, file.id);
}

throw e;
}

eventStop(event);
Expand Down

0 comments on commit 945136d

Please sign in to comment.