package sqlstore import ( "context" "fmt" "strconv" "github.com/mattermost/focalboard/server/model" "github.com/mattermost/focalboard/server/utils" "github.com/mattermost/mattermost-server/v6/shared/mlog" ) const ( UniqueIDsMigrationKey = "UniqueIDsMigrationComplete" ) func (s *SQLStore) runUniqueIDsMigration() error { setting, err := s.GetSystemSetting(UniqueIDsMigrationKey) if err != nil { return fmt.Errorf("cannot get migration state: %w", err) } // If the migration is already completed, do not run it again. if hasAlreadyRun, _ := strconv.ParseBool(setting); hasAlreadyRun { return nil } s.logger.Debug("Running Unique IDs migration") tx, txErr := s.db.BeginTx(context.Background(), nil) if txErr != nil { return txErr } blocks, err := s.getBlocksWithSameID(tx) if err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { s.logger.Error("unique IDs transaction rollback error", mlog.Err(rollbackErr), mlog.String("methodName", "getBlocksWithSameID")) } return fmt.Errorf("cannot get blocks with same ID: %w", err) } blocksByID := map[string][]model.Block{} for _, block := range blocks { blocksByID[block.ID] = append(blocksByID[block.ID], block) } for _, blocks := range blocksByID { for i, block := range blocks { if i == 0 { // do nothing for the first ID, only updating the others continue } newID := utils.NewID(model.BlockType2IDType(block.Type)) if err := s.replaceBlockID(tx, block.ID, newID, block.WorkspaceID); err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { s.logger.Error("unique IDs transaction rollback error", mlog.Err(rollbackErr), mlog.String("methodName", "replaceBlockID")) } return fmt.Errorf("cannot replace blockID %s: %w", block.ID, err) } } } if err := s.setSystemSetting(tx, UniqueIDsMigrationKey, strconv.FormatBool(true)); err != nil { if rollbackErr := tx.Rollback(); rollbackErr != nil { s.logger.Error("unique IDs transaction rollback error", mlog.Err(rollbackErr), mlog.String("methodName", "setSystemSetting")) } return fmt.Errorf("cannot mark migration as completed: %w", err) } if err := tx.Commit(); err != nil { return fmt.Errorf("cannot commit unique IDs transaction: %w", err) } s.logger.Debug("Unique IDs migration finished successfully") return nil }