// IRepository is the interface for the repositories.
type IRepository[T any] interface {
GetDB() *gorm.DB
GetModel() *gorm.DB
Create(ctx context.Context, value *T) error
CreateInTransaction(ctx context.Context, db *gorm.DB, value *T) error
Find(ctx context.Context, filter T) (list []T, err error)
FindInTransaction(ctx context.Context, db *gorm.DB, filter T) (list []T, err error)
Get(ctx context.Context, entity *T) (err error)
GetInTransaction(ctx context.Context, db *gorm.DB, entity *T) (err error)
Update(ctx context.Context, entity T) (updated *T, err error)
UpdateInTransaction(ctx context.Context, db *gorm.DB, entity T) (updated *T, err error)
Delete(ctx context.Context, id string) (deleted bool, err error)
DeleteInTransaction(ctx context.Context, db *gorm.DB, id string) (deleted bool, err error)
}
// Repository is the repository for the models.
type Repository[T interface{}] struct {
db *gorm.DB
}
func setup[T interface{}](ctx context.Context, r *Repository[T]) error {
_, span := tr.Start(ctx, "repo-setup")
defer span.End()
span.SetAttributes(attribute.Key("model").String(fmt.Sprintf("%T", new(T))))
r.db = database.GetConn()
err := r.db.AutoMigrate(new(T))
return err
}
// GetDB returns the database connection.
func (r Repository[T]) GetDB() *gorm.DB {
return r.db
}
func (r Repository[T]) GetModel() *gorm.DB {
return r.db.Model(new(T))
}
// Create creates a new entity.
func (r Repository[T]) Create(ctx context.Context, value *T) error {
return r.CreateInTransaction(ctx, r.db, value)
}
// CreateWithDB creates a new entity in a transaction.
func (r Repository[T]) CreateInTransaction(ctx context.Context, db *gorm.DB, value *T) error {
_, span := tr.Start(ctx, "repo-create")
defer span.End()
span.SetAttributes(attribute.Key("entity").String(fmt.Sprintf("%T", new(T))))
model := db.Model(new(T))
result := model.Create(value)
if result.Error != nil {
log.Errorf("error on insert the result into model: %v", result.Error)
return result.Error
}
if result.RowsAffected != 1 {
err := errors.New("error on insert not inserted")
log.Error(err)
return err
}
return nil
}
// Find finds entities.
func (r Repository[T]) Find(ctx context.Context, filter T) (list []T, err error) {
return r.FindInTransaction(ctx, r.db, filter)
}
// FindWithDB finds entities in a transaction.
func (r Repository[T]) FindInTransaction(ctx context.Context, db *gorm.DB, filter T) (list []T, err error) {
_, span := tr.Start(ctx, "repo-find")
defer span.End()
span.SetAttributes(attribute.Key("entity").String(fmt.Sprintf("%T", new(T))))
model := db.Model(filter)
result := model.Find(&list, filter)
err = result.Error
if err != nil {
log.Errorf("Error on find: %v", err)
return
}
return
}
// Get gets an entity.
func (r Repository[T]) Get(ctx context.Context, entity *T) (err error) {
return r.GetInTransaction(ctx, r.db, entity)
}
// GetWithDB gets an entity in a transaction.
func (r Repository[T]) GetInTransaction(ctx context.Context, db *gorm.DB, entity *T) (err error) {
_, span := tr.Start(ctx, "repo-get")
defer span.End()
span.SetAttributes(attribute.Key("entity").String(fmt.Sprintf("%T", new(T))))
model := db.Model(entity)
result := model.First(entity, entity)
err = result.Error
if err != nil {
log.Errorf("Error on find one result into collection: %v", err)
return
}
return
}
// Update updates an entity.
func (r Repository[T]) Update(ctx context.Context, entity T) (updated *T, err error) {
return r.UpdateInTransaction(ctx, r.db, entity)
}
// UpdateWithDB updates an entity in a transaction.
func (r Repository[T]) UpdateInTransaction(ctx context.Context, db *gorm.DB, entity T) (updated *T, err error) {
_, span := tr.Start(ctx, "repo-update")
defer span.End()
span.SetAttributes(attribute.Key("entity").String(fmt.Sprintf("%T", new(T))))
model := db.Model(entity)
result := model.Updates(entity)
err = result.Error
if err != nil {
log.Errorf("Error on update into collection: %v", err)
return
}
updated = &entity
return
}
// Delete deletes an entity.
func (r Repository[T]) Delete(ctx context.Context, id string) (deleted bool, err error) {
return r.DeleteInTransaction(ctx, r.db, id)
}
// DeleteWithDB deletes an entity in a transaction.
func (r Repository[T]) DeleteInTransaction(ctx context.Context, db *gorm.DB, id string) (deleted bool, err error) {
_, span := tr.Start(ctx, "repo-delete")
defer span.End()
span.SetAttributes(attribute.Key("entity").String(fmt.Sprintf("%T", new(T))))
model := db.Model(new(T))
result := model.Delete(id)
err = result.Error
if err != nil {
log.Errorf("Error on delete from collection: %v", err)
return
}
deleted = result.RowsAffected == 1
return
}