Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

oracledb.queueTimeout set to 0, but the queued connection requests are never terminated #1338

Closed
menghu07 opened this issue Feb 6, 2021 · 2 comments
Labels

Comments

@menghu07
Copy link

menghu07 commented Feb 6, 2021

  1. Oracle Version: Oracle 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
    Platform: win32
    Version: v12.13.1
    Arch: x64
    Version String: 5.0.0
    Client Version String: 12.1.0.2.0

  2. When I set database pool's queueTimeout 0, the queued connection requests are quickly terminated. The document API says when queueTimeout is 0, the queued connection requests are never terminated.

  3. The input command like this:
    In node-oracledb-5.0.0 root directory, and run node_modules\.bin\mocha test\pool.js, only test use case test/pool.js 2.8.2 generates NJS-040.
    Output:

  1. pool.js
    2.8 connection request queue
    (node:20180) UnhandledPromiseRejectionWarning: AssertionError: expected null to exist
    at F:\ideaworkspace\node-oracledb-5.0.0\test\pool.js:737:28
    at F:\ideaworkspace\node-oracledb-5.0.0\lib\util.js:182:7
    (node:20180) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
    (node:20180) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
  1. Code in here, node-oracledb-5.0.0/test/pool.js, modify the queueTimeout :0:
  describe('2.8 connection request queue', function(){

    function getBlockingSql(secondsToBlock) {
      var blockingSql = '' +
        'declare \n' +
        ' \n' +
        '  l_start timestamp with local time zone := systimestamp; \n' +
        ' \n' +
        'begin \n' +
        ' \n' +
        '  loop \n' +
        '    exit when l_start + interval \'' + (secondsToBlock || 3) + '\' second <= systimestamp; \n' +
        '  end loop; \n' +
        ' \n' +
        'end;';

      return blockingSql;
    }
it('2.8.2 generates NJS-040 if request is queued and queueTimeout expires', function(done) {
      oracledb.createPool(
        {
          user              : dbConfig.user,
          password          : dbConfig.password,
          connectString     : dbConfig.connectString,
          poolMin           : 0,
          poolMax           : 1,
          poolIncrement     : 1,
          poolTimeout       : 1,
          queueTimeout      : 0  //0 seconds
        },
        function(err, pool){
          should.not.exist(err);

          async.parallel(
            [
              function(cb) {
                pool.getConnection(function(err, conn) {
                  should.not.exist(err);

                  conn.execute(getBlockingSql(4), function(err) {
                    should.not.exist(err);
                    conn.release(function(err) {
                      should.not.exist(err);
                      cb();
                    });
                  });
                });
              },
              function(cb) {
                //using setTimeout to help ensure this gets to the db last
                setTimeout(function() {
                  pool.getConnection(function(err, conn) {
                    should.exist(err);
                    (err.message.startsWith("NJS-040:")).should.be.true();

                    should.not.exist(conn);
                    cb();
                  });
                }, 100);
              }
            ],
            function(err){
              should.not.exist(err);
              pool.terminate(function(err) {
                should.not.exist(err);
                done();
              });
            }
          );
        }
      );
    });
  1. My Thought, I see the node-oracledb-5.0.0/lib/pool.js file async function getConnection(a1) method line:117 this._queueTimeout !== 0 is always true, because this._queueTimeout is undefined.
if (this._connectionsOut >= poolMax) {

    // when the queue is huge, throw error early without waiting for queue timeout
    if (this._connRequestQueue.length >= this.queueMax && this.queueMax >= 0) {
      if (this._enableStats) {
        this._totalRequestsRejected += 1;
      }
      throw new Error(nodbUtil.getErrorMessage('NJS-076', this.queueMax));
    }

    // if too many connections are out, wait until room is made available or the
    // queue timeout expires
    await new Promise((resolve, reject) => {

      // set up a payload which will be added to the queue for processing
      const payload = { resolve: resolve, reject: reject };

      // if using a queue timeout, establish the timeout so that when it
      // expires the payload will be removed from the queue and an exception
      // thrown
      if (this._queueTimeout !== 0) {
        payload.timeoutHandle = setTimeout(() => {
          const ix = this._connRequestQueue.indexOf(payload);
          if (ix >= 0) {
            this._connRequestQueue.splice(ix, 1);
          }
          if (this._enableStats) {
            this._totalRequestTimeouts += 1;
            this._totalTimeInQueue += Date.now() - payload.enqueuedTime;
          }
          reject(new Error(nodbUtil.getErrorMessage('NJS-040',
            this.queueTimeout)));
        }, this.queueTimeout);
      }

      // add payload to the queue
      this._connRequestQueue.push(payload);
      if (this._enableStats) {
        payload.enqueuedTime = Date.now();
        this._totalRequestsEnqueued += 1;
        this._maxQueueLength = Math.max(this._maxQueueLength,
          this._connRequestQueue.length);
      }

    });

    // check if pool is draining or closed after delay has completed and throw
    // an appropriate error if so
    this._checkPoolOpen();

  }
@menghu07 menghu07 added the bug label Feb 6, 2021
@cjbj
Copy link
Member

cjbj commented Feb 6, 2021

Thanks!

cjbj added a commit that referenced this issue Apr 13, 2021
@cjbj
Copy link
Member

cjbj commented Apr 13, 2021

See 8cbd79f

Thanks for reporting it.

@cjbj cjbj closed this as completed May 30, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants