Uploaded image for project: 'Go Driver'
  1. Go Driver
  2. GODRIVER-3380

Change stream should resume with CSOT failure

    • Type: Icon: Bug Bug
    • Resolution: Unresolved
    • Priority: Icon: Minor - P4 Minor - P4
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • Go Drivers
    • Hide

      1. What would you like to communicate to the user about this feature?
      2. Would you like the user to see examples of the syntax and/or executable code and its output?
      3. Which versions of the driver/connector does this apply to?

      Show
      1. What would you like to communicate to the user about this feature? 2. Would you like the user to see examples of the syntax and/or executable code and its output? 3. Which versions of the driver/connector does this apply to?

      Detailed steps to reproduce the problem?

      The CSOT specifications note that

      If a next call fails with a timeout error, drivers MUST NOT invalidate the change stream. The subsequent next call MUST perform a resume attempt to establish a new change stream on the server.

      However, the Go Driver invalidates the change stream

      func Test_3006_ChangeStream(t *testing.T) {
      	monitor := newMonitor(true, "getMore")
      
      	opts := options.Client().SetMonitor(monitor.commandMonitor)
      
      	client, err := mongo.Connect(opts)
      	require.NoError(t, err, "failed to connect to server")
      
      	defer func() {
      		t.Log("about to disconnect")
      		_ = client.Disconnect(context.Background())
      	}()
      
      	coll := client.Database("db").Collection("coll")
      
      	csOpts := options.ChangeStream().SetBatchSize(1)
      
      	cs, err := coll.Watch(context.Background(), mongo.Pipeline{}, csOpts)
      	require.NoError(t, err)
      
      	defer cs.Close(context.Background())
      
      	// Insert 5 documents
      	for i := 0; i < 5; i++ {
      		_, err = coll.InsertOne(context.Background(), bson.D{})
      		require.NoError(t, err)
      	}
      
      	ok := cs.Next(context.Background())
      	assert.True(t, ok)
      
      	// Create a FP that will block the next "getMore" call causing the CS next
      	// to fail with a CSOT.
      	teardown, err := createBlockFP(t, client, "getMore", 500, 1)
      	require.NoError(t, err)
      
      	defer teardown()
      
      	ctx, cancel := context.WithTimeout(context.Background(), 150*time.Millisecond)
      	defer cancel()
      
      	ok = cs.Next(ctx)
      	assert.False(t, ok)
      
      	// A subsequent call to next that does not time out should resume since the
      	// error was CSOT.
      	ok = cs.Next(context.Background())
      	assert.True(t, ok)
      }
      

      Definition of done: what must be done to consider the task complete?

      Do not invalidate the change stream for CSOT errors. Likely we just need to check if the error is a timeout, here.

      The exact Go version used, with patch level:

      go version go1.23.1 darwin/arm64

      The exact version of the Go driver used:

      2.0.0-beta2

      Describe how MongoDB is set up. Local vs Hosted, version, topology, load balanced, etc.

      Connecting to:          mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.3.1
      Using MongoDB:          8.0.0-rc18
      Using Mongosh:          2.3.1
      

      The operating system and version (e.g. Windows 7, OSX 10.8, ...)

      OSX Sonoma 14.5

      Security Vulnerabilities

      NA

            Assignee:
            preston.vasquez@mongodb.com Preston Vasquez
            Reporter:
            preston.vasquez@mongodb.com Preston Vasquez
            Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

              Created:
              Updated: