-
Type:
Bug
-
Resolution: Fixed
-
Priority:
Major - P3
-
Affects Version/s: None
-
Component/s: None
-
None
-
🔵 Done
-
Go Drivers
-
Not Needed
-
-
None
-
None
-
None
-
None
-
None
-
None
Detailed steps to reproduce the problem?
According to the CSOT specifications, the timeoutMS value must apply to cursor iteration methods such as cursor.Next():
When applying the timeoutMS option to next calls on cursor, drivers MUST ensure it applies to the entire call, not individual commands.
To reproduce:
func TestClientLevelTimeoutForCursors(t *testing.T) {
client, err := mongo.Connect(options.Client().SetTimeout(500 * time.Millisecond))
require.NoError(t, err, "failed to connect to server")
t.Cleanup(func() {
_ = client.Disconnect(context.Background())
})
db := client.Database("exampleDB")
collName := "exampleCappedCollection"
// Drop the collection if it exists
_ = db.Collection(collName).Drop(context.Background())
// Create a capped collection.
collOpts := options.CreateCollection().SetCapped(true).SetSizeInBytes(1024 * 1024) // 1 MB capped collection
err = db.CreateCollection(context.Background(), collName, collOpts)
require.NoError(t, err, "failed to create capped collection")
coll := db.Collection(collName)
// Insert some documents to ensure the collection exists
_, err = coll.InsertMany(context.Background(), []interface{}{
bson.D{{Key: "name", Value: "Alice"}},
bson.D{{Key: "name", Value: "Bob"}},
bson.D{{Key: "name", Value: "Charlie"}},
})
require.NoError(t, err, "failed to insert documents")
opts := options.Find().SetMaxAwaitTime(10 * time.Second).SetBatchSize(3).SetCursorType(options.TailableAwait)
res, err := coll.Find(context.Background(), bson.D{}, opts)
if err != nil {
t.Logf("error running Find with MaxAwaitTime: %v", err)
}
fmt.Println("Cursor created with MaxAwaitTime set to 10 seconds")
//assert.Error(t, err, "expected validation error when using MaxAwaitTime with a non-capped collection")
// What happens if we use the decoder?
for res.Next(context.Background()) {
fmt.Println("Found document:", res.Current)
}
if err := res.Err(); err != nil {
t.Errorf("cursor error: %v", err)
}
}
Output:
❯ go test -run "TestClientLevelTimeoutForCursors" -v -failfast === RUN TestClientLevelTimeoutForCursors Cursor created with MaxAwaitTime set to 10 seconds Found document: {"_id": {"$oid":"687ed19e6478f989450d6e9b"},"name": "Alice"} Found document: {"_id": {"$oid":"687ed19e6478f989450d6e9c"},"name": "Bob"} Found document: {"_id": {"$oid":"687ed19e6478f989450d6e9d"},"name": "Charlie"}
Blocks indefinitely, running a getMore every 10 seconds=maxAwaitTimeMS:
{"getMore": {"$numberLong":"2425290832589901730"},"collection": "exampleCappedCollection","batchSize": {"$numberInt":"3"},"maxTimeMS": {"$numberLong":"10000"},"lsid": {"id": {"$binary":{"base64":"S8lu41B+R726FrVRyjWk0g==","subType":"04"}}},"$clusterTime": {"clusterTime": {"$timestamp":{"t":1753141637,"i":5}},"signature": {"hash": {"$binary":{"base64":"AAAAAAAAAAAAAAAAAAAAAAAAAAA=","subType":"00"}},"keyId": {"$numberLong":"0"}}},"$db": "exampleDB"}
Definition of done: what must be done to consider the task complete?
The methods that use (*mongo.Cursor).next() should respect the effective timeoutMS for the full duration of the call, both for the operational level context deadlines (supported) and client-level timeouts.
- related to
-
GODRIVER-3473 Incorrect Validation of timeoutMS for Tailable AwaitData Cursors
-
- Closed
-
-
GODRIVER-3444 Clarify maxAwaitTimeMS adjustment by timeoutMS and RTT
-
- Closed
-