Uploaded image for project: 'Node.js Driver'
  1. Node.js Driver
  2. NODE-5203

Emit INIT event from ChangeStream

    • Type: Icon: Improvement Improvement
    • Resolution: Won't Fix
    • Priority: Icon: Unknown Unknown
    • None
    • Affects Version/s: None
    • Component/s: None
    • 3
    • Not Needed
    • 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?

      How are you using Mongo? What version of the server and driver are you using?

      Mongo server: v4.4
      Mongo driver: v5.2.0

      What is the feature/improvement you would like?

      Emit INIT event from ChangeStream

      What use case would this feature/improvement enable?

      We currently have a test that runs against MongoDB and looks like this:

      it('subscribes to a change stream', async () => {
        const mongo = await new MongoClient(...).connect();
        const changeStream = mongo.collection(...).watch(...);
        
        mongo.collection(...).insertOne({...});
        await new Promise((resolve) => changeStream.once('change', resolve));
      })
      

      Most of the time (~99%), this test passes fine, even with the synchronous calls of ChangeStream.watch() followed immediately by Collection.insertOne()

      However, this occasionally fails. I've done some digging and the cases where it fails are when the change stream's cursor is initialised later than the insertion completes (which is understandable).

      What I'd like to do is change the test (and similar code that relies on a stream being initialised) to look like this:

      it('subscribes to a change stream', async () => {
        const mongo = await new MongoClient(...).connect();
        const changeStream = mongo.collection(...).watch(...);
      
        // This line was added and would ensure our stream is subscribed
        // before trying to manipulate the collection:
        await new Promise((resolve) => changeStream.once('init', resolve));
      
        mongo.collection(...).insertOne({...});
        await new Promise((resolve) => changeStream.once('change', resolve));
      });

      The docs actually claim that INIT is already a valid event, but the source code would beg to differ.

      Note that I've tested with:

      await new Promise((resolve) => changeStream.cursor.once('init', resolve));

      And this seems to work as expected, but cursor is obviously marked @internal.

            Assignee:
            warren.james@mongodb.com Warren James
            Reporter:
            alec@reedys.com Alec Gibson
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: