Skip to content

Conversation

@onematchfox
Copy link
Contributor

Split this out of #1133 to try reduce the size of that PR - but also because it's not strictly related to being able to scale the controller - it simply manifested when needing to switch to postgres when running multiple controller replicas.

Signed-off-by: Brian Fox <878612+onematchfox@users.noreply.github.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the database upsert logic to properly work with both PostgreSQL and SQLite by replacing the previous "try-create-then-save-on-error" approach with GORM's native OnConflict clause. This change enables the controller to scale across multiple replicas with PostgreSQL while maintaining backward compatibility with SQLite for single-replica deployments.

Key changes:

  • Replaces the dual-operation upsert (Create + Save on error) with a single atomic upsert using clause.OnConflict{UpdateAll: true}
  • Removes the TODO comment indicating the previous implementation wasn't truly idempotent
  • Updates error message to reflect the actual operation being performed

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 53 to 60
func save[T Model](db *gorm.DB, model *T) error {
if err := db.Create(model).Error; err != nil {
if err == gorm.ErrDuplicatedKey {
return db.Save(model).Error
}
return fmt.Errorf("failed to create model: %w", err)
if err := db.Clauses(clause.OnConflict{
UpdateAll: true,
}).Create(model).Error; err != nil {
return fmt.Errorf("failed to upsert model: %w", err)
}
return nil
}
Copy link

Copilot AI Nov 26, 2025

Choose a reason for hiding this comment

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

The updated save function lacks test coverage to verify the upsert behavior works correctly with both PostgreSQL and SQLite. Given that this change is specifically to ensure compatibility across database backends, consider adding tests that:

  1. Verify the upsert correctly inserts new records
  2. Verify the upsert updates existing records (especially with composite primary keys like Event, Session, Tool, etc.)
  3. Test with both SQLite and PostgreSQL to ensure the behavior is consistent
  4. Verify that CreatedAt and UpdatedAt timestamps are handled correctly on conflict

Copilot uses AI. Check for mistakes.
@EItanya EItanya merged commit 837dd5c into kagent-dev:main Dec 1, 2025
23 checks passed
@onematchfox onematchfox deleted the fix-postgres-upserts branch December 2, 2025 07:55
GTRekter pushed a commit to GTRekter/kagent that referenced this pull request Dec 4, 2025
…ent-dev#1137)

Split this out of kagent-dev#1133 to try reduce the size of that PR - but also
because it's not strictly related to being able to scale the controller
- it simply manifested when needing to switch to postgres when running
multiple controller replicas.

Signed-off-by: Brian Fox <878612+onematchfox@users.noreply.github.com>
Signed-off-by: Ivan Porta <porta.ivan@outlook.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants