Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions event/monitoring.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type CommandSucceededEvent struct {
type CommandFailedEvent struct {
CommandFinishedEvent
Failure error
Codes []int32
}

// CommandMonitor represents a monitor that is triggered for different events.
Expand Down
33 changes: 32 additions & 1 deletion internal/integration/clam_prose_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ import (

"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/internal/assert"
"go.mongodb.org/mongo-driver/v2/internal/failpoint"
"go.mongodb.org/mongo-driver/v2/internal/integration/mtest"
"go.mongodb.org/mongo-driver/v2/internal/integtest"
"go.mongodb.org/mongo-driver/v2/internal/logger"
"go.mongodb.org/mongo-driver/v2/internal/require"
"go.mongodb.org/mongo-driver/v2/mongo"
"go.mongodb.org/mongo-driver/v2/mongo/options"
)
Expand Down Expand Up @@ -198,7 +200,6 @@ func clamMultiByteTruncLogs(mt *mtest.T) []truncValidator {

// Insert started.
validators[0] = newTruncValidator(mt, cmd, func(cmd string) error {

// Remove the suffix from the command string.
cmd = cmd[:len(cmd)-len(logger.TruncationSuffix)]

Expand Down Expand Up @@ -396,3 +397,33 @@ func TestCommandLoggingAndMonitoringProse(t *testing.T) {
})
}
}

func TestCommandFailedEvent_Codes(t *testing.T) {
clientOpts := options.Client().SetRetryWrites(false)

mtOpts := mtest.NewOptions().MinServerVersion("8.0").ClientType(mtest.Pinned).ClientOptions(clientOpts)
mt := mtest.New(t, mtOpts)

mt.Run("Top level code", func(mt *mtest.T) {
mt.ResetClient(options.Client().SetRetryWrites(false))

mt.SetFailPoint(failpoint.FailPoint{
ConfigureFailPoint: "failCommand",
Mode: failpoint.Mode{
Times: 1,
},
Data: failpoint.Data{
FailCommands: []string{"insert"},
ErrorCode: 1,
},
})

_, err := mt.Coll.InsertOne(context.Background(), struct{ X int }{X: 1})
require.Error(mt, err, "expected InsertOne error, got nil")

failedEvent := mt.GetFailedEvent()

require.NotNil(mt, failedEvent, "expected CommandFailedEvent, got nil")
require.Equal(mt, []int32{1}, failedEvent.Codes, "expected Codes to be [1], got %+v", failedEvent.Codes)
})
}
10 changes: 6 additions & 4 deletions mongo/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -364,10 +364,12 @@ func hasErrorCode(srvErr ServerError, code int) bool {
return false
}

var _ ServerError = CommandError{}
var _ ServerError = WriteError{}
var _ ServerError = WriteException{}
var _ ServerError = BulkWriteException{}
var (
_ ServerError = CommandError{}
_ ServerError = WriteError{}
_ ServerError = WriteException{}
_ ServerError = BulkWriteException{}
)

var _ error = ClientBulkWriteException{}

Expand Down
22 changes: 22 additions & 0 deletions x/mongo/driver/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -566,3 +566,25 @@ func ExtractErrorFromServerResponse(doc bsoncore.Document) error {

return nil
}

// errorCodes extracts error codes from a driver.Error representing an ok:0
// command failure. Since ok:0 indicates the command failed before processing
// any operations, only a single error code is returned. Returns nil if the
// error is not a driver.Error (e.g., network errors, WriteCommandError for
// ok:1 responses).
//
// This function may be updated in the future to extract multiple error codes in
// an ok:1 scenario. In such cases, there can be multiple error codes via
// WriteErrors which represent individual operation failures within the context
// of a write command.
func errorCodes(err error) []int32 {
switch e := err.(type) {
case Error:
return []int32{e.Code}
case *Error:
if e != nil {
return []int32{e.Code}
}
}
return nil
}
2 changes: 1 addition & 1 deletion x/mongo/driver/operation.go
Original file line number Diff line number Diff line change
Expand Up @@ -747,7 +747,6 @@ func (op Operation) Execute(ctx context.Context) error {
var moreToCome bool
var startedInfo startedInformation
*wm, moreToCome, startedInfo, err = op.createWireMessage(ctx, maxTimeMS, (*wm)[:0], desc, conn, requestID)

if err != nil {
return err
}
Expand Down Expand Up @@ -2231,6 +2230,7 @@ func (op Operation) publishFinishedEvent(ctx context.Context, info finishedInfor

failedEvent := &event.CommandFailedEvent{
Failure: info.cmdErr,
Codes: errorCodes(info.cmdErr),
CommandFinishedEvent: finished,
}
op.CommandMonitor.Failed(ctx, failedEvent)
Expand Down
Loading