Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-30848

getMore requests do not use a session in the mongo shell

    • Type: Icon: Bug Bug
    • Resolution: Fixed
    • Priority: Icon: Major - P3 Major - P3
    • 3.6.0-rc0
    • Affects Version/s: None
    • Component/s: Shell
    • Labels:
    • Fully Compatible
    • ALL
    • Hide
      /**
       * Tests that "getMore" commands use the same session id as the original "find" command when a
       * cursor is created in the mongo shell.
       */
      (function() {
          "use strict";
      
          load("jstests/libs/parallelTester.js");
      
          const conn = MongoRunner.runMongod({});
      
          const db = conn.startSession().getDatabase("test");
          const coll = db.repro_nosession_getmore;
      
          const insertRes = coll.insert([{}, {}, {}, {}, {}]);
          assert.writeOK(insertRes);
          assert.eq(5, insertRes.nInserted);
      
          const triggeredFind = new CountDownLatch(1);
          const triggerGetMore = new CountDownLatch(1);
      
          function runFindAndThenGetMore(host, triggeredFind, triggerGetMore) {
              try {
                  const conn = new Mongo(host);
                  const db = conn.startSession().getDatabase("test");
                  const coll = db.repro_nosession_getmore;
      
                  const cursor = coll.find().batchSize(2);
                  cursor.next();
                  cursor.next();
      
                  triggeredFind.countDown();
                  triggerGetMore.await();
      
                  cursor.next();
                  return {ok: 1};
              } catch (e) {
                  return {ok: 0, error: e.toString(), stack: e.stack};
              }
          }
      
          assert.commandWorked(conn.adminCommand({setParameter: 1, internalQueryExecYieldIterations: 1}));
          assert.commandWorked(
              conn.adminCommand({configureFailPoint: "setYieldAllLocksHang", mode: "alwaysOn"}));
      
          //
          // Run a "find" command and verify that it has a session id.
          //
      
          const cursorThread =
              new ScopedThread(runFindAndThenGetMore, conn.host, triggeredFind, triggerGetMore);
          cursorThread.start();
      
          let op;
          let currentOpRes;
      
          assert.soon(
              function() {
                  currentOpRes = assert.commandWorked(db.currentOp({ns: coll.getFullName()}));
                  if (currentOpRes.inprog.length === 1 && currentOpRes.inprog[0].numYields > 0) {
                      op = currentOpRes.inprog[0];
                      return true;
                  }
                  return false;
              },
              function() {
                  return "Failed to find operation in currentOp() output: " + tojson(currentOpRes);
              });
      
          assert(op.hasOwnProperty("lsid"),
                 "Expected 'find' command to have a session id: " + tojson(op));
          const sessionId = op.lsid;
      
          // Disable the failpoint and wait until 'cursorThread' has consumed the documents returned in
          // the "find" command's initial batch.
          assert.commandWorked(
              conn.adminCommand({configureFailPoint: "setYieldAllLocksHang", mode: "off"}));
      
          triggeredFind.await();
      
          assert.commandWorked(
              conn.adminCommand({configureFailPoint: "setYieldAllLocksHang", mode: "alwaysOn"}));
      
          triggerGetMore.countDown();
      
          //
          // Run a "getMore" command and verify that it has the same session id as the "find" command.
          //
      
          assert.soon(
              function() {
                  currentOpRes = assert.commandWorked(db.currentOp({ns: coll.getFullName()}));
                  if (currentOpRes.inprog.length === 1 && currentOpRes.inprog[0].numYields > 0) {
                      op = currentOpRes.inprog[0];
                      return true;
                  }
                  return false;
              },
              function() {
                  return "Failed to find operation in currentOp() output: " + tojson(currentOpRes);
              });
      
          assert.eq(sessionId,
                    op.lsid,
                    "Expected 'getMore' command to have the same session id: " + tojson(op));
      
          // Disable the failpoint and wait for 'cursorThread' to exit.
          assert.commandWorked(
              conn.adminCommand({configureFailPoint: "setYieldAllLocksHang", mode: "off"}));
      
          cursorThread.join();
          assert.commandWorked(cursorThread.returnData());
      
          MongoRunner.stopMongod(conn);
      })();
      
      Show
      /** * Tests that "getMore" commands use the same session id as the original "find" command when a * cursor is created in the mongo shell. */ ( function () { "use strict" ; load( "jstests/libs/parallelTester.js" ); const conn = MongoRunner.runMongod({}); const db = conn.startSession().getDatabase( "test" ); const coll = db.repro_nosession_getmore; const insertRes = coll.insert([{}, {}, {}, {}, {}]); assert.writeOK(insertRes); assert.eq(5, insertRes.nInserted); const triggeredFind = new CountDownLatch(1); const triggerGetMore = new CountDownLatch(1); function runFindAndThenGetMore(host, triggeredFind, triggerGetMore) { try { const conn = new Mongo(host); const db = conn.startSession().getDatabase( "test" ); const coll = db.repro_nosession_getmore; const cursor = coll.find().batchSize(2); cursor.next(); cursor.next(); triggeredFind.countDown(); triggerGetMore.await(); cursor.next(); return {ok: 1}; } catch (e) { return {ok: 0, error: e.toString(), stack: e.stack}; } } assert.commandWorked(conn.adminCommand({setParameter: 1, internalQueryExecYieldIterations: 1})); assert.commandWorked( conn.adminCommand({configureFailPoint: "setYieldAllLocksHang" , mode: "alwaysOn" })); // // Run a "find" command and verify that it has a session id. // const cursorThread = new ScopedThread(runFindAndThenGetMore, conn.host, triggeredFind, triggerGetMore); cursorThread.start(); let op; let currentOpRes; assert.soon( function () { currentOpRes = assert.commandWorked(db.currentOp({ns: coll.getFullName()})); if (currentOpRes.inprog.length === 1 && currentOpRes.inprog[0].numYields > 0) { op = currentOpRes.inprog[0]; return true ; } return false ; }, function () { return "Failed to find operation in currentOp() output: " + tojson(currentOpRes); }); assert(op.hasOwnProperty( "lsid" ), "Expected 'find' command to have a session id: " + tojson(op)); const sessionId = op.lsid; // Disable the failpoint and wait until 'cursorThread' has consumed the documents returned in // the "find" command's initial batch. assert.commandWorked( conn.adminCommand({configureFailPoint: "setYieldAllLocksHang" , mode: "off" })); triggeredFind.await(); assert.commandWorked( conn.adminCommand({configureFailPoint: "setYieldAllLocksHang" , mode: "alwaysOn" })); triggerGetMore.countDown(); // // Run a "getMore" command and verify that it has the same session id as the "find" command. // assert.soon( function () { currentOpRes = assert.commandWorked(db.currentOp({ns: coll.getFullName()})); if (currentOpRes.inprog.length === 1 && currentOpRes.inprog[0].numYields > 0) { op = currentOpRes.inprog[0]; return true ; } return false ; }, function () { return "Failed to find operation in currentOp() output: " + tojson(currentOpRes); }); assert.eq(sessionId, op.lsid, "Expected 'getMore' command to have the same session id: " + tojson(op)); // Disable the failpoint and wait for 'cursorThread' to exit. assert.commandWorked( conn.adminCommand({configureFailPoint: "setYieldAllLocksHang" , mode: "off" })); cursorThread.join(); assert.commandWorked(cursorThread.returnData()); MongoRunner.stopMongod(conn); })();
    • Platforms 2017-10-02, Platforms 2017-10-23
    • 21

      The DBCommandCursor object wraps a Mongo connection object, which doesn't have a notion of being associated with a ServerSession object. This causes "getMore" operations on the cursor to not be sent with a logical session id associated with them.

            Assignee:
            mira.carey@mongodb.com Mira Carey
            Reporter:
            max.hirschhorn@mongodb.com Max Hirschhorn
            Votes:
            0 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated:
              Resolved: