In fact, you could consider inserting directly into the concurrent map without constructing a separate map locally. Then read
would look something like
func (r *clientRepo) read(ctx context.Context, spn log.Span, file string, bucket string) error {
// Initialize the reader as before.
pr := ...
for {
rows, err := pr.ReadByNumber(r.cfg.RowsToRead)
if err != nil {
return err
}
if len(rows) <= 0 {
break
}
byteSlice, err := json.Marshal(rows)
if err != nil {
return err
}
var productRows []ClientProduct
err = json.Unmarshal(byteSlice, &productRows)
if err != nil {
return err
}
for i := range productRows {
// Going with the idea that Convert returns
// a CustomerProduct.
flatProduct, err := r.Convert(spn, productRows[i])
if err != nil {
return err
}
if flatProduct.StatusCode == definitions.DONE {
continue
}
r.products.Set(strconv.Itoa(flatProduct.ProductId, 10), flatProduct)
for _, catalogId := range flatProduct.Catalogs {
catalogValue := strconv.FormatInt(int64(catalogId), 10)
r.productCatalog.Upsert(catalogValue, flatProduct.ProductId, func(exists bool, valueInMap interface{}, newValue interface{}) interface{} {
if valueInMap == nil {
return newValue
}
oldIDs := valueInMap.([]int64)
productID := newValue.(int64)
for _, id := range oldIDs {
if id == productID {
// Already exists, don't add duplicates.
return oldIDs
}
}
return append(oldIDs, productID)
})
}
}
}
return nil
}
This uses a linear scan to check for duplicate product IDs, upso it will be faster than allocating a map if the number of IDs is small. Up to you to test the performance of this suggestion.