package mysqlkindbox import ( "context" "log" "git.gocasts.ir/ebhomengo/niki/entity" errmsg "git.gocasts.ir/ebhomengo/niki/pkg/err_msg" richerror "git.gocasts.ir/ebhomengo/niki/pkg/rich_error" ) func (d DB) AddBatchKindBox(ctx context.Context, kindBoxes []entity.KindBox) ([]entity.KindBox, error) { const op = "mysqlkindbox.AddBatchKindBoxConcurrentlyRollback" errCh := make(chan error, len(kindBoxes)) resultCh := make(chan entity.KindBox, len(kindBoxes)) tx, tErr := d.conn.Conn().Begin() if tErr != nil { return nil, richerror.New(op).WithErr(tErr). WithMessage(errmsg.ErrorMsgSomethingWentWrong).WithKind(richerror.KindUnexpected) } for _, kindBox := range kindBoxes { go func(kb entity.KindBox) { res, err := tx.ExecContext(ctx, "insert into kind_boxes (kind_box_req_id, benefactor_id, type, serial_number, status) values (?, ?, ?, ?, ?);", kb.KindBoxReqID, kb.BenefactorID, kb.Type.String(), kb.SerialNumber, kb.Status.String(), ) if err != nil { errCh <- richerror.New(op).WithErr(err). WithMessage(errmsg.ErrorMsgSomethingWentWrong).WithKind(richerror.KindUnexpected) return } //nolint // err is always nil id, _ := res.LastInsertId() kb.ID = uint(id) resultCh <- kb errCh <- nil }(kindBox) } var result []entity.KindBox for i := 0; i < len(kindBoxes); i++ { select { case err := <-errCh: if err != nil { if err := tx.Rollback(); err != nil { log.Printf("Rollback error: %v", err) } return nil, err } case res := <-resultCh: result = append(result, res) case <-ctx.Done(): if err := tx.Rollback(); err != nil { log.Printf("Rollback error: %v", err) } return nil, richerror.New(op).WithErr(ctx.Err()). WithMessage(errmsg.ErrorMsgSomethingWentWrong).WithKind(richerror.KindUnexpected) } } if err := tx.Commit(); err != nil { log.Printf("Commit error: %v", err) return nil, richerror.New(op).WithErr(err). WithMessage(errmsg.ErrorMsgSomethingWentWrong).WithKind(richerror.KindUnexpected) } return result, nil }