From ad2b57bf21b98c09a63533060be0f5385140df59 Mon Sep 17 00:00:00 2001 From: Felipe Gasper Date: Fri, 24 Apr 2026 16:28:02 -0400 Subject: [PATCH] implement --- mongo/client_bulk_write.go | 24 +++++----- mongo/errors.go | 89 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 10 deletions(-) diff --git a/mongo/client_bulk_write.go b/mongo/client_bulk_write.go index bf3a1e530..1785195d0 100644 --- a/mongo/client_bulk_write.go +++ b/mongo/client_bulk_write.go @@ -102,6 +102,7 @@ func (bw *clientBulkWrite) execute(ctx context.Context) error { Message: ce.Message, Raw: ce.Raw, }, + Labels: ce.Labels, } } if len(batches.writeConcernErrors) > 0 || len(batches.writeErrors) > 0 { @@ -435,16 +436,17 @@ func (mb *modelBatches) processResponse(ctx context.Context, resp bsoncore.Docum return nil } var res struct { - Ok bool - Cursor bsoncore.Document - NDeleted int32 - NInserted int32 - NMatched int32 - NModified int32 - NUpserted int32 - NErrors int32 - Code int32 - Errmsg string + Ok bool + Cursor bsoncore.Document + NDeleted int32 + NInserted int32 + NMatched int32 + NModified int32 + NUpserted int32 + NErrors int32 + Code int32 + Errmsg string + ErrorLabels []string } err := bson.Unmarshal(resp, &res) if err != nil { @@ -460,6 +462,7 @@ func (mb *modelBatches) processResponse(ctx context.Context, resp bsoncore.Docum WriteConcernErrors: mb.writeConcernErrors, WriteErrors: mb.writeErrors, PartialResult: mb.result, + Labels: res.ErrorLabels, } } @@ -520,6 +523,7 @@ func (mb *modelBatches) processResponse(ctx context.Context, resp bsoncore.Docum WriteConcernErrors: mb.writeConcernErrors, WriteErrors: mb.writeErrors, PartialResult: mb.result, + Labels: writeCmdErr.Labels, } } return nil diff --git a/mongo/errors.go b/mongo/errors.go index 28c298c5f..bd57141a1 100644 --- a/mongo/errors.go +++ b/mongo/errors.go @@ -378,6 +378,7 @@ var ( _ ServerError = WriteError{} _ ServerError = WriteException{} _ ServerError = BulkWriteException{} + _ ServerError = ClientBulkWriteException{} ) var _ error = ClientBulkWriteException{} @@ -797,6 +798,94 @@ type ClientBulkWriteException struct { // The results of any successful operations that were performed before the error // was encountered. PartialResult *ClientBulkWriteResult + + Labels []string +} + +func (bwe ClientBulkWriteException) serverError() {} + +// ErrorCodes returns the list of server error codes contained in the error. +func (bwe ClientBulkWriteException) ErrorCodes() []int { + errorCodes := []int{} + + bwe.iterateErrors(func(code int, _ string) bool { + errorCodes = append(errorCodes, code) + return false + }) + + return errorCodes +} + +// HasErrorCode returns true if the error has the specified code. +func (bwe ClientBulkWriteException) HasErrorCode(code int) bool { + for _, errorCode := range bwe.ErrorCodes() { + if errorCode == code { + return true + } + } + + return false +} + +// HasErrorCodeWithMessage returns true if any of the contained errors have the specified code and message. +func (bwe ClientBulkWriteException) HasErrorCodeWithMessage(code int, message string) bool { + has := false + bwe.iterateErrors(func(errCode int, errMsg string) bool { + if errCode == code && strings.Contains(errMsg, message) { + has = true + return true + } + + return false + }) + + return has +} + +// HasErrorMessage returns true if the error contains the specified message. +func (bwe ClientBulkWriteException) HasErrorMessage(message string) bool { + has := false + bwe.iterateErrors(func(_ int, errMsg string) bool { + if strings.Contains(errMsg, message) { + has = true + return true + } + + return false + }) + + return has +} + +// HasErrorLabel returns true if the error contains the specified label. +func (bwe ClientBulkWriteException) HasErrorLabel(label string) bool { + for _, l := range bwe.Labels { + if l == label { + return true + } + } + + return false +} + +func (bwe ClientBulkWriteException) iterateErrors(f func(int, string) bool) { + if bwe.WriteError != nil { + if f(bwe.WriteError.Code, bwe.WriteError.Message) { + return + } + } + + for _, err := range bwe.WriteConcernErrors { + if f(err.Code, err.Message) { + return + } + } + + for _, writeError := range bwe.WriteErrors { + if f(writeError.Code, writeError.Message) { + return + } + } } // Error implements the error interface.