-
-
Notifications
You must be signed in to change notification settings - Fork 251
Fix SQLite deadlock with recurring tasks #1053
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
04f8754
40c85db
ec20769
8ace5c7
c9d168c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -7,7 +7,6 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "image" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "io" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "io/fs" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "net/http" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "path/filepath" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "runtime" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -442,19 +441,16 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (r *AttachmentRepo) CreateThumbnail(ctx context.Context, groupId, attachmentId uuid.UUID, title string, path string) error { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Debug().Msg("starting thumbnail creation") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tx, err := r.db.Tx(ctx) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // If there is an error during file creation rollback the database | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Cleanup: always rollback the transaction and ignore errors to prevent leaving connections open | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defer func() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if v := recover(); v != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Debug().Msg("set initial database transaction") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| att := tx.Attachment.Create(). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| SetID(uuid.New()). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -465,49 +461,23 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| bucket, err := blob.OpenBucket(ctx, r.GetConnString()) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to open bucket") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defer func(bucket *blob.Bucket) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := bucket.Close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to close bucket") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }(bucket) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| origFile, err := bucket.Open(r.fullPath(path)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| defer func(file fs.File) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := file.Close() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to close file") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }(origFile) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Debug().Msg("stat original file for file size") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| stats, err := origFile.Stat() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to stat original file") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -519,10 +489,6 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Debug().Msg("reading original file content") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| contentBytes, err := io.ReadAll(origFile) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to read original file content") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -547,30 +513,17 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| img, _, err := image.Decode(bytes.NewReader(contentBytes)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to decode image file") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to rollback transaction") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Debug().Msg("reading original file orientation") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imageMeta, err := imagemeta.Decode(bytes.NewReader(contentBytes)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to decode original file content") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| orientation := uint16(imageMeta.Orientation) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| thumbnailPath, err := r.processThumbnailFromImage(ctx, groupId, img, title, orientation) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| att.SetPath(thumbnailPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -579,29 +532,17 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| img, err := webp.Decode(bytes.NewReader(contentBytes)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to decode webp image") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Debug().Msg("reading original file orientation") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imageMeta, err := imagemeta.Decode(bytes.NewReader(contentBytes)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to decode original file content") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| orientation := uint16(imageMeta.Orientation) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| thumbnailPath, err := r.processThumbnailFromImage(ctx, groupId, img, title, orientation) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| att.SetPath(thumbnailPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -610,18 +551,10 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| img, err := avif.Decode(bytes.NewReader(contentBytes)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to decode avif image") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| thumbnailPath, err := r.processThumbnailFromImage(ctx, groupId, img, title, uint16(1)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| att.SetPath(thumbnailPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -630,29 +563,17 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| img, err := heic.Decode(bytes.NewReader(contentBytes)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to decode avif image") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Debug().Msg("reading original file orientation") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| imageMeta, err := imagemeta.Decode(bytes.NewReader(contentBytes)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to decode original file content") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| orientation := uint16(imageMeta.Orientation) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| thumbnailPath, err := r.processThumbnailFromImage(ctx, groupId, img, title, orientation) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| att.SetPath(thumbnailPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -661,18 +582,10 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| img, err := jpegxl.Decode(bytes.NewReader(contentBytes)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to decode avif image") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| thumbnailPath, err := r.processThumbnailFromImage(ctx, groupId, img, title, uint16(1)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err := tx.Rollback() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| att.SetPath(thumbnailPath) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -694,9 +607,10 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Debug().Msg("finishing thumbnail creation transaction") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err := tx.Commit(); err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = tx.Commit() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to commit transaction") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -721,33 +635,33 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to open pubsub topic") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| count := 0 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !r.thumbnail.Enabled { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return 0, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+638
to
+640
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion | 🟠 Major Move the thumbnail enabled check before pubsub setup. The early return for disabled thumbnails (lines 638-640) occurs after establishing the pubsub connection (lines 629-636). This wastes resources by opening a topic that won't be used. Apply this diff to check the flag first: if err != nil {
return 0, err
}
- pubsubString, err := utils.GenerateSubPubConn(r.pubSubConn, "thumbnails")
- if err != nil {
- log.Err(err).Msg("failed to generate pubsub connection string")
- }
- topic, err := pubsub.OpenTopic(ctx, pubsubString)
- if err != nil {
- log.Err(err).Msg("failed to open pubsub topic")
- }
-
if !r.thumbnail.Enabled {
return 0, nil
}
+ pubsubString, err := utils.GenerateSubPubConn(r.pubSubConn, "thumbnails")
+ if err != nil {
+ log.Err(err).Msg("failed to generate pubsub connection string")
+ return 0, err
+ }
+ topic, err := pubsub.OpenTopic(ctx, pubsubString)
+ if err != nil {
+ log.Err(err).Msg("failed to open pubsub topic")
+ return 0, err
+ }
+
var messages []*pubsub.Message📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| var messages []*pubsub.Message | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, attachment := range attachments { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if r.thumbnail.Enabled { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !attachment.QueryThumbnail().ExistX(ctx) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if count > 0 && count%100 == 0 { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| time.Sleep(2 * time.Second) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = topic.Send(ctx, &pubsub.Message{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Body: []byte(fmt.Sprintf("attachment_created:%s", attachment.ID.String())), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Metadata: map[string]string{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "group_id": groupId.String(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "attachment_id": attachment.ID.String(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "title": attachment.Title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "path": attachment.Path, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to send message to topic") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| continue | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| count++ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if !attachment.QueryThumbnail().ExistX(ctx) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| msg := &pubsub.Message{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Body: fmt.Appendf(nil, "attachment_created:%s", attachment.ID.String()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Metadata: map[string]string{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "group_id": groupId.String(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "attachment_id": attachment.ID.String(), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "title": attachment.Title, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "path": attachment.Path, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| messages = append(messages, msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+644
to
+655
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Avoid Ent’s ExistX (panics on error); handle existence check errors ExistX will panic on DB errors. Use Exist(ctx) and handle err. - if !attachment.QueryThumbnail().ExistX(ctx) {
+ exists, err := attachment.QueryThumbnail().Exist(ctx)
+ if err != nil {
+ log.Err(err).
+ Str("group_id", groupId.String()).
+ Str("attachment_id", attachment.ID.String()).
+ Msg("failed to check thumbnail existence")
+ return 0, err
+ }
+ if !exists {
msg := &pubsub.Message{
Body: fmt.Appendf(nil, "attachment_created:%s", attachment.ID.String()),
Metadata: map[string]string{
"group_id": groupId.String(),
"attachment_id": attachment.ID.String(),
"title": attachment.Title,
"path": attachment.Path,
},
}
messages = append(messages, msg)
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for _, msg := range messages { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = topic.Send(ctx, msg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Err(err).Msg("failed to send 'attachment_created' message to topic 'thumbnails'") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return count, nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return len(messages), nil | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+642
to
+664
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Major: Silent message loss on send failures. The current implementation collects messages in a slice and sends them individually (line 744). When Consider one of these approaches:
Apply this diff to fail fast on send errors: for _, msg := range messages {
err = topic.Send(ctx, msg)
if err != nil {
log.Err(err).Msg("failed to send 'attachment_created' message to topic 'thumbnails'")
+ return 0, fmt.Errorf("failed to send message to thumbnails topic: %w", err)
}
}
return len(messages), nilAlternatively, to aggregate errors and return partial success count: + sent := 0
for _, msg := range messages {
err = topic.Send(ctx, msg)
if err != nil {
log.Err(err).Msg("failed to send 'attachment_created' message to topic 'thumbnails'")
+ } else {
+ sent++
}
}
- return len(messages), nil
+ if sent < len(messages) {
+ return sent, fmt.Errorf("failed to send %d of %d messages", len(messages)-sent, len(messages))
+ }
+ return sent, nil🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func (r *AttachmentRepo) UploadFile(ctx context.Context, itemGroup *ent.Group, doc ItemCreateAttachment) (string, error) { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -861,6 +775,7 @@ | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Debug().Msg("uploading thumbnail file") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Get the group for uploading the thumbnail | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Debug().Msg(fmt.Sprintf("OpenConnections = %d", r.db.Debug().Sql().Stats().OpenConnections)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| group, err := r.db.Group.Get(ctx, groupId) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Compile-time issue: invalid call chain to DB stats ent.Client doesn’t expose Sql(); use DB() to access database/sql stats. - log.Debug().Msg(fmt.Sprintf("OpenConnections = %d", r.db.Debug().Sql().Stats().OpenConnections))
+ log.Debug().Int("open_connections", r.db.DB().Stats().OpenConnections).Msg("DB stats")📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return "", err | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle or explicitly ignore the Rollback error.
The deferred
tx.Rollback()on line 447 ignores its error return value, which the static analysis tool correctly flags. While callingRollback()after a successfulCommit()is a no-op, the error should be explicitly ignored or handled to satisfy linters and make the intent clear.Apply this diff to explicitly ignore the error:
// Cleanup: always rollback the transaction and ignore errors to prevent leaving connections open defer func() { - tx.Rollback() + _ = tx.Rollback() }()📝 Committable suggestion
🧰 Tools
🪛 GitHub Check: Backend Server Tests / Go
[failure] 447-447:
Error return value of
tx.Rollbackis not checked (errcheck)🤖 Prompt for AI Agents