fix(05): WR-02 delete thumb blob after a failed encode
This commit is contained in:
@@ -89,7 +89,7 @@ func defaultResizeImage(src image.Image, w, h int, mode string) image.Image {
|
|||||||
|
|
||||||
var resizeImage = defaultResizeImage
|
var resizeImage = defaultResizeImage
|
||||||
|
|
||||||
func encodeImage(w io.Writer, img image.Image, ext string) error {
|
func defaultEncodeImage(w io.Writer, img image.Image, ext string) error {
|
||||||
format := imaging.JPEG
|
format := imaging.JPEG
|
||||||
switch strings.ToLower(ext) {
|
switch strings.ToLower(ext) {
|
||||||
case "png":
|
case "png":
|
||||||
@@ -100,6 +100,8 @@ func encodeImage(w io.Writer, img image.Image, ext string) error {
|
|||||||
return imaging.Encode(w, img, format)
|
return imaging.Encode(w, img, format)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var encodeImage = defaultEncodeImage
|
||||||
|
|
||||||
// Thumb returns the public URL of a lazily generated thumbnail. The second
|
// Thumb returns the public URL of a lazily generated thumbnail. The second
|
||||||
// call for the same dimensions hits the existing blob and does not resize.
|
// call for the same dimensions hits the existing blob and does not resize.
|
||||||
func (f *File) Thumb(ctx context.Context, bucket *blob.Bucket, w, h int, mode string) (string, error) {
|
func (f *File) Thumb(ctx context.Context, bucket *blob.Bucket, w, h int, mode string) (string, error) {
|
||||||
@@ -164,10 +166,11 @@ func (f *File) Thumb(ctx context.Context, bucket *blob.Bucket, w, h int, mode st
|
|||||||
}
|
}
|
||||||
encErr := encodeImage(wr, resized, ext)
|
encErr := encodeImage(wr, resized, ext)
|
||||||
closeErr = wr.Close()
|
closeErr = wr.Close()
|
||||||
if encErr != nil {
|
if encErr != nil || closeErr != nil {
|
||||||
return "", encErr
|
_ = deleteKey(ctx, bucket, thumbKey)
|
||||||
}
|
if encErr != nil {
|
||||||
if closeErr != nil {
|
return "", encErr
|
||||||
|
}
|
||||||
return "", closeErr
|
return "", closeErr
|
||||||
}
|
}
|
||||||
return publicURL(thumbKey), nil
|
return publicURL(thumbKey), nil
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package attach
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"image/jpeg"
|
"image/jpeg"
|
||||||
@@ -129,6 +130,46 @@ func TestFileThumbResizesOnce(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestFileThumbEncodeFailureDoesNotCache(t *testing.T) {
|
||||||
|
ctx := t.Context()
|
||||||
|
bucket := memblob.OpenBucket(nil)
|
||||||
|
t.Cleanup(func() { _ = bucket.Close() })
|
||||||
|
|
||||||
|
f := &File{ID: 7, DiskName: "abc123xyz.jpg"}
|
||||||
|
if err := bucket.WriteAll(ctx, BlobKey(f.DiskName), testJPEG(t), &blob.WriterOptions{ContentType: "image/jpeg"}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
orig := encodeImage
|
||||||
|
encodeImage = func(w io.Writer, img image.Image, ext string) error {
|
||||||
|
_, _ = w.Write([]byte("partial"))
|
||||||
|
return errors.New("encode boom")
|
||||||
|
}
|
||||||
|
t.Cleanup(func() { encodeImage = orig })
|
||||||
|
|
||||||
|
if _, err := f.Thumb(ctx, bucket, 200, 200, "crop"); err == nil {
|
||||||
|
t.Fatal("encode failure must surface")
|
||||||
|
}
|
||||||
|
thumbKey := PartitionDirectory(f.DiskName) + ThumbFilename(f.ID, 200, 200, 0, 0, "crop", "jpg")
|
||||||
|
exists, err := bucket.Exists(ctx, thumbKey)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
t.Fatal("failed encode must not leave a cached thumb blob")
|
||||||
|
}
|
||||||
|
|
||||||
|
encodeImage = orig
|
||||||
|
url, err := f.Thumb(ctx, bucket, 200, 200, "crop")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("retry after failed encode: %v", err)
|
||||||
|
}
|
||||||
|
want := "/storage/uploads/abc/123/xyz/thumb_7_200_200_0_0_crop.jpg"
|
||||||
|
if url != want {
|
||||||
|
t.Fatalf("retry url = %q, want %q", url, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func testJPEG(t *testing.T) []byte {
|
func testJPEG(t *testing.T) []byte {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
img := image.NewRGBA(image.Rect(0, 0, 8, 8))
|
img := image.NewRGBA(image.Rect(0, 0, 8, 8))
|
||||||
|
|||||||
Reference in New Issue
Block a user