Skip to content

Commit 4e0ab11

Browse files
GODRIVER-3086 Add ErrorCodes to ServerError API (#1894)
1 parent 50cf0c2 commit 4e0ab11

File tree

2 files changed

+116
-14
lines changed

2 files changed

+116
-14
lines changed

mongo/errors.go

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -252,9 +252,25 @@ type ServerError interface {
252252
// HasErrorCodeWithMessage returns true if any of the contained errors have the specified code and message.
253253
HasErrorCodeWithMessage(int, string) bool
254254

255+
// ErrorCodes returns all error codes (unsorted) in the server’s response.
256+
// This would include nested errors (e.g., write concern errors) for
257+
// supporting implementations (e.g., BulkWriteException) as well as the
258+
// top-level error code.
259+
ErrorCodes() []int
260+
255261
serverError()
256262
}
257263

264+
func hasErrorCode(srvErr ServerError, code int) bool {
265+
for _, srvErrCode := range srvErr.ErrorCodes() {
266+
if code == srvErrCode {
267+
return true
268+
}
269+
}
270+
271+
return false
272+
}
273+
258274
var _ ServerError = CommandError{}
259275
var _ ServerError = WriteError{}
260276
var _ ServerError = WriteException{}
@@ -290,6 +306,11 @@ func (e CommandError) HasErrorCode(code int) bool {
290306
return int(e.Code) == code
291307
}
292308

309+
// ErrorCodes returns a list of error codes returned by the server.
310+
func (e CommandError) ErrorCodes() []int {
311+
return []int{int(e.Code)}
312+
}
313+
293314
// HasErrorLabel returns true if the error contains the specified label.
294315
func (e CommandError) HasErrorLabel(label string) bool {
295316
for _, l := range e.Labels {
@@ -345,6 +366,11 @@ func (we WriteError) HasErrorCode(code int) bool {
345366
return we.Code == code
346367
}
347368

369+
// ErrorCodes returns a list of error codes returned by the server.
370+
func (we WriteError) ErrorCodes() []int {
371+
return []int{we.Code}
372+
}
373+
348374
// HasErrorLabel returns true if the error contains the specified label. WriteErrors do not contain labels,
349375
// so we always return false.
350376
func (we WriteError) HasErrorLabel(string) bool {
@@ -451,15 +477,21 @@ func (mwe WriteException) Error() string {
451477

452478
// HasErrorCode returns true if the error has the specified code.
453479
func (mwe WriteException) HasErrorCode(code int) bool {
454-
if mwe.WriteConcernError != nil && mwe.WriteConcernError.Code == code {
455-
return true
480+
return hasErrorCode(mwe, code)
481+
}
482+
483+
// ErrorCodes returns a list of error codes returned by the server.
484+
func (mwe WriteException) ErrorCodes() []int {
485+
errorCodes := []int{}
486+
for _, writeError := range mwe.WriteErrors {
487+
errorCodes = append(errorCodes, writeError.Code)
456488
}
457-
for _, we := range mwe.WriteErrors {
458-
if we.Code == code {
459-
return true
460-
}
489+
490+
if mwe.WriteConcernError != nil {
491+
errorCodes = append(errorCodes, mwe.WriteConcernError.Code)
461492
}
462-
return false
493+
494+
return errorCodes
463495
}
464496

465497
// HasErrorLabel returns true if the error contains the specified label.
@@ -563,15 +595,21 @@ func (bwe BulkWriteException) Error() string {
563595

564596
// HasErrorCode returns true if any of the errors have the specified code.
565597
func (bwe BulkWriteException) HasErrorCode(code int) bool {
566-
if bwe.WriteConcernError != nil && bwe.WriteConcernError.Code == code {
567-
return true
598+
return hasErrorCode(bwe, code)
599+
}
600+
601+
// ErrorCodes returns a list of error codes returned by the server.
602+
func (bwe BulkWriteException) ErrorCodes() []int {
603+
errorCodes := []int{}
604+
for _, writeError := range bwe.WriteErrors {
605+
errorCodes = append(errorCodes, writeError.Code)
568606
}
569-
for _, we := range bwe.WriteErrors {
570-
if we.Code == code {
571-
return true
572-
}
607+
608+
if bwe.WriteConcernError != nil {
609+
errorCodes = append(errorCodes, bwe.WriteConcernError.Code)
573610
}
574-
return false
611+
612+
return errorCodes
575613
}
576614

577615
// HasErrorLabel returns true if the error contains the specified label.

mongo/errors_test.go

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,70 @@ func TestIsTimeout(t *testing.T) {
679679
}
680680
}
681681

682+
func TestServerError_ErrorCodes(t *testing.T) {
683+
tests := []struct {
684+
name string
685+
error ServerError
686+
want []int
687+
}{
688+
{
689+
name: "CommandError",
690+
error: CommandError{Code: 1},
691+
want: []int{1},
692+
},
693+
{
694+
name: "WriteError",
695+
error: WriteError{Code: 1},
696+
want: []int{1},
697+
},
698+
{
699+
name: "WriteException single",
700+
error: WriteException{WriteErrors: []WriteError{{Code: 1}}},
701+
want: []int{1},
702+
},
703+
{
704+
name: "WriteException multiple",
705+
error: WriteException{WriteErrors: []WriteError{{Code: 1}, {Code: 2}}},
706+
want: []int{1, 2},
707+
},
708+
{
709+
name: "WriteException duplicates",
710+
error: WriteException{WriteErrors: []WriteError{{Code: 1}, {Code: 2}, {Code: 2}}},
711+
want: []int{1, 2, 2},
712+
},
713+
{
714+
name: "BulkWriteException single",
715+
error: BulkWriteException{WriteErrors: []BulkWriteError{{WriteError: WriteError{Code: 1}}}},
716+
want: []int{1},
717+
},
718+
{
719+
name: "BulkWriteException multiple",
720+
error: BulkWriteException{WriteErrors: []BulkWriteError{
721+
{WriteError: WriteError{Code: 1}},
722+
{WriteError: WriteError{Code: 2}},
723+
}},
724+
want: []int{1, 2},
725+
},
726+
{
727+
name: "BulkWriteException duplicates",
728+
error: BulkWriteException{WriteErrors: []BulkWriteError{
729+
{WriteError: WriteError{Code: 1}},
730+
{WriteError: WriteError{Code: 2}},
731+
{WriteError: WriteError{Code: 2}},
732+
}},
733+
want: []int{1, 2, 2},
734+
},
735+
}
736+
737+
for _, test := range tests {
738+
t.Run(test.name, func(t *testing.T) {
739+
got := test.error.ErrorCodes()
740+
741+
assert.ElementsMatch(t, got, test.want)
742+
})
743+
}
744+
}
745+
682746
type netErr struct {
683747
timeout bool
684748
}

0 commit comments

Comments
 (0)