fix(user,customer): return 409 on phone duplicate-key races
Map E11000 from the per-collection phone index to friendly conflict errors and skip redundant GetByPhone when the phone is unchanged. Not blocking: IAT test DB may need a one-off dedupe for index build; phone uniqueness is per collection (users vs customers), not global.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
package mongo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
|
||||
mongodriver "go.mongodb.org/mongo-driver/v2/mongo"
|
||||
)
|
||||
|
||||
// IsDuplicateKeyError reports whether err is a MongoDB E11000 duplicate key error.
|
||||
func IsDuplicateKeyError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
if strings.Contains(err.Error(), "E11000") || strings.Contains(err.Error(), "duplicate key") {
|
||||
return true
|
||||
}
|
||||
var we mongodriver.WriteException
|
||||
if errors.As(err, &we) {
|
||||
for _, wErr := range we.WriteErrors {
|
||||
if wErr.Code == 11000 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// DuplicateKeyMatchesField reports whether a duplicate key error involves the given field
|
||||
// (e.g. "phone" matches index phone_idx or dup key { phone: "..." }).
|
||||
func DuplicateKeyMatchesField(err error, field string) bool {
|
||||
if err == nil || field == "" {
|
||||
return false
|
||||
}
|
||||
msg := strings.ToLower(err.Error())
|
||||
field = strings.ToLower(field)
|
||||
if strings.Contains(msg, field+"_idx") {
|
||||
return true
|
||||
}
|
||||
if strings.Contains(msg, "dup key") && strings.Contains(msg, field) {
|
||||
return true
|
||||
}
|
||||
return strings.Contains(msg, `"`+field+`"`) || strings.Contains(msg, field+":")
|
||||
}
|
||||
Reference in New Issue
Block a user