Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions backend/app/api/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,9 @@ func run(cfg *config.Config) error {

if strings.ToLower(cfg.Database.Driver) == "sqlite3" {
db := c.Sql()
db.SetMaxOpenConns(1)
db.SetMaxIdleConns(1)
log.Info().Msg("SQLite connection pool configured: max_open=1, max_idle=1")
db.SetMaxOpenConns(4)
db.SetMaxIdleConns(4)
log.Info().Msg("SQLite connection pool configured: max_open=4, max_idle=4")
}

migrationsFs, err := migrations.Migrations(strings.ToLower(cfg.Database.Driver))
Expand Down
45 changes: 23 additions & 22 deletions backend/internal/data/repo/repo_item_attachments.go
Original file line number Diff line number Diff line change
Expand Up @@ -721,33 +721,33 @@ func (r *AttachmentRepo) CreateMissingThumbnails(ctx context.Context, groupId uu
log.Err(err).Msg("failed to open pubsub topic")
}

count := 0
if !r.thumbnail.Enabled {
return 0, nil
}
Comment on lines +638 to +640
Copy link
Contributor

Choose a reason for hiding this comment

The 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

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if !r.thumbnail.Enabled {
return 0, nil
}
if err != nil {
return 0, err
}
// bail out early if thumbnails are disabled, before opening any topics
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
🤖 Prompt for AI Agents
In backend/internal/data/repo/repo_item_attachments.go around lines 629 to 640,
move the check for whether thumbnails are enabled (lines 638-640) to before the
pubsub setup (lines 629-636). This avoids opening the pubsub topic unnecessarily
when thumbnails are disabled. To fix, place the if !r.thumbnail.Enabled { return
0, nil } condition before any pubsub connection or topic initialization occurs.


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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

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

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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)
}
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)
}
🤖 Prompt for AI Agents
In backend/internal/data/repo/repo_item_attachments.go lines 730 to 741, replace
the use of attachment.QueryThumbnail().ExistX(ctx) with
attachment.QueryThumbnail().Exist(ctx) and properly handle the returned error.
Check if an error occurred during the existence check, and handle it accordingly
instead of letting the code panic. Proceed with the logic only if no error
occurs and the thumbnail exists or not.

}
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Major: Silent message loss on send failures.

The current implementation collects messages in a slice and sends them individually (line 744). When topic.Send() fails (line 745), the error is only logged (lines 746-747), and the message is silently dropped. This means thumbnail generation requests can be lost without any indication to the user.

Consider one of these approaches:

  1. Fail fast: Return an error on first failure
  2. Aggregate errors: Collect all errors and return them
  3. Use batch send: If the pubsub implementation supports it

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), nil

Alternatively, 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
In backend/internal/data/repo/repo_item_attachments.go around lines 728-750 the
code currently logs failures from topic.Send and silently drops messages; change
this to fail fast by returning the error immediately when topic.Send(ctx, msg)
fails. Update the error handling to wrap/annotate the returned error with
context (e.g., group_id and attachment_id or the message body) and return the
current count of successfully queued messages or simply return the error
(depending on calling conventions), instead of only logging; ensure no message
send failure is ignored.

}

func (r *AttachmentRepo) UploadFile(ctx context.Context, itemGroup *ent.Group, doc ItemCreateAttachment) (string, error) {
Expand Down Expand Up @@ -861,6 +861,7 @@ func (r *AttachmentRepo) processThumbnailFromImage(ctx context.Context, groupId
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

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

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
group, err := r.db.Group.Get(ctx, groupId)
// Replace the invalid Sql() call on ent.Client with DB()
log.Debug().
Int("open_connections", r.db.DB().Stats().OpenConnections).
Msg("DB stats")
group, err := r.db.Group.Get(ctx, groupId)
🤖 Prompt for AI Agents
In backend/internal/data/repo/repo_item_attachments.go at line 865, the call
chain to access database statistics is incorrect because ent.Client does not
have a Sql() method. Replace the use of Sql() with DB() to correctly access the
underlying database/sql instance and its stats. Adjust the code to call DB() on
the ent.Client or relevant DB object instead of Sql().

if err != nil {
return "", err
Expand Down
Loading