From dd17b2c4ccf8f2cfc38a02a15d33ba8b40b665ac Mon Sep 17 00:00:00 2001 From: Bobby <30593201+luciferreeves@users.noreply.github.com> Date: Mon, 9 Feb 2026 13:38:49 +0530 Subject: Refactor BatchCreateProducers: implement transaction handling and improve error logging; add title and external URL associations --- repositories/producer.go | 47 +++++++++++++++++++++++++++++++++++----------- tasks/producersync.task.go | 39 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 11 deletions(-) diff --git a/repositories/producer.go b/repositories/producer.go index 946d873..53deefe 100644 --- a/repositories/producer.go +++ b/repositories/producer.go @@ -5,7 +5,6 @@ import ( "metachan/entities" "metachan/utils/logger" - "gorm.io/gorm" "gorm.io/gorm/clause" ) @@ -30,17 +29,43 @@ func BatchCreateProducers(producers []entities.Producer) error { return nil } - result := DB.Session(&gorm.Session{FullSaveAssociations: true}).Clauses(clause.OnConflict{ - Columns: []clause.Column{{Name: "mal_id"}}, - DoUpdates: clause.AssignmentColumns([]string{ - "url", "favorites", "count", "established", "about", "image_id", - }), - }).CreateInBatches(&producers, 100) + tx := DB.Begin() + defer func() { + if r := recover(); r != nil { + tx.Rollback() + } + }() - if result.Error != nil { - logger.Errorf("Producer", "Failed to batch create producers: %v", result.Error) - return errors.New("failed to batch create producers") + for i := range producers { + result := tx.Clauses(clause.OnConflict{ + Columns: []clause.Column{{Name: "mal_id"}}, + DoUpdates: clause.AssignmentColumns([]string{ + "url", "favorites", "count", "established", "about", "image_id", + }), + }).Omit("Titles", "ExternalURLs").Create(&producers[i]) + + if result.Error != nil { + tx.Rollback() + logger.Errorf("Producer", "Failed to create producer %d: %v", producers[i].MALID, result.Error) + return errors.New("failed to batch create producers") + } + + if len(producers[i].Titles) > 0 { + if err := tx.Model(&producers[i]).Association("Titles").Replace(producers[i].Titles); err != nil { + tx.Rollback() + logger.Errorf("Producer", "Failed to associate titles for producer %d: %v", producers[i].MALID, err) + return errors.New("failed to batch create producers") + } + } + + if len(producers[i].ExternalURLs) > 0 { + if err := tx.Model(&producers[i]).Association("ExternalURLs").Replace(producers[i].ExternalURLs); err != nil { + tx.Rollback() + logger.Errorf("Producer", "Failed to associate external URLs for producer %d: %v", producers[i].MALID, err) + return errors.New("failed to batch create producers") + } + } } - return nil + return tx.Commit().Error } diff --git a/tasks/producersync.task.go b/tasks/producersync.task.go index 6949e70..8c8bb79 100644 --- a/tasks/producersync.task.go +++ b/tasks/producersync.task.go @@ -94,6 +94,25 @@ func ProducerSync() error { } } + titleMap := make(map[string]entities.SimpleTitle) + for _, pd := range producersData { + for _, title := range pd.producer.Titles { + key := title.Type + ":" + title.Title + titleMap[key] = title + } + } + + if len(titleMap) > 0 { + titles := make([]entities.SimpleTitle, 0, len(titleMap)) + for _, title := range titleMap { + titles = append(titles, title) + } + if err := repositories.BatchCreateSimpleTitles(titles); err != nil { + logger.Errorf("ProducerSync", "Failed to batch insert titles: %v", err) + return err + } + } + var dbImages []entities.SimpleImage if err := repositories.DB.Select("id, image_url").Find(&dbImages).Error; err != nil { logger.Errorf("ProducerSync", "Failed to query images: %v", err) @@ -105,6 +124,18 @@ func ProducerSync() error { imageIDMap[img.ImageURL] = img.ID } + var dbTitles []entities.SimpleTitle + if err := repositories.DB.Select("id, type, title").Find(&dbTitles).Error; err != nil { + logger.Errorf("ProducerSync", "Failed to query titles: %v", err) + return err + } + + titleIDMap := make(map[string]uint) + for _, title := range dbTitles { + key := title.Type + ":" + title.Title + titleIDMap[key] = title.ID + } + producers := make([]entities.Producer, 0, len(producersData)) for _, pd := range producersData { if pd.imageURL != "" { @@ -112,6 +143,14 @@ func ProducerSync() error { pd.producer.ImageID = &id } } + + for i := range pd.producer.Titles { + key := pd.producer.Titles[i].Type + ":" + pd.producer.Titles[i].Title + if id, exists := titleIDMap[key]; exists { + pd.producer.Titles[i].ID = id + } + } + producers = append(producers, pd.producer) } -- cgit v1.2.3