tediousjs/tedious-connection-pool

Issue with connection closed

PeterNierop opened this issue · 13 comments

I got this if somehow the connection is closed

Tedious-Connection-Pool: connection reset: 1
Tedious-Connection-Pool: acquired connection 1
{ RequestError: SHUTDOWN is in progress.
at RequestError (F:\TestConnection\node_modules\tedious\lib\errors.js:34:12)
at Parser. (F:\TestConnection\node_modules\tedious\lib\connection.js:207:36)
at emitOne (events.js:96:13)
at Parser.emit (events.js:188:7)
at Parser. (F:\TestConnection\node_modules\tedious\lib\token\token-stream-parser.js:42:15)
at emitOne (events.js:96:13)
at Parser.emit (events.js:188:7)
at readableAddChunk (F:\TestConnection\node_modules\readable-stream\lib_stream_readable.js:210:18)
at Parser.Readable.push (F:\TestConnection\node_modules\readable-stream\lib_stream_readable.js:169:10)
at Parser.Transform.push (F:\TestConnection\node_modules\readable-stream\lib_stream_transform.js:123:32)
at doneParsing (F:\TestConnection\node_modules\tedious\lib\token\stream-parser.js:87:17)
message: 'SHUTDOWN is in progress.',
code: 'EREQUEST',
number: 6005,
state: 2,
class: 14,
serverName: 'MGL-ACS-KABA',
procName: '',
lineNumber: 1 }
Tedious-Connection-Pool: connection closing because of error
{ ConnectionError: Connection lost - read ECONNRESET
at ConnectionError (F:\TestConnection\node_modules\tedious\lib\errors.js:12:12)
at Connection.socketError (F:\TestConnection\node_modules\tedious\lib\connection.js:535:28)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at emitErrorNT (net.js:1272:8)
at _combinedTickCallback (internal/process/next_tick.js:74:11)
at process._tickCallback (internal/process/next_tick.js:98:9)
message: 'Connection lost - read ECONNRESET',
code: 'ESOCKET' }
F:\TestConnection\node_modules\tedious-connection-pool\lib\connection-pool.js:243
pooled.con.close();
^

TypeError: Cannot read property 'close' of undefined
at F:\TestConnection\node_modules\tedious-connection-pool\lib\connection-pool.js:243:31
at Request.userCallback (F:\TestConnection\node_modules\tedious\lib\connection.js:938:16)
at Request.callback (F:\TestConnection\node_modules\tedious\lib\request.js:33:27)
at Connection.socketError (F:\TestConnection\node_modules\tedious\lib\connection.js:1168:20)
at Connection.dispatchEvent (F:\TestConnection\node_modules\tedious\lib\connection.js:519:45)
at Connection.socketError (F:\TestConnection\node_modules\tedious\lib\connection.js:537:19)
at emitOne (events.js:96:13)
at Socket.emit (events.js:188:7)
at emitErrorNT (net.js:1272:8)
at _combinedTickCallback (internal/process/next_tick.js:74:11)

I got a similar issue. I fixed it in my by providing a call back in the connection:

ConnectionPool.prototype.release = function(connection, callback)

I think this would be a useful feature in the API. Can we add it?

While 50 dollar is not much, I did put up a bonus which is yours if you can provide me with a worked out example of how to do that. Pardon my noob status. I come from Microsoft land... so what you describe is just not yet in my grasp.
To claim reward please find this: https://www.bountysource.com/issues/34547563-failed-to-connect
If you have some example please mail to peternierop@yahoo.com
Thank you very much

@PeterNierop, will you please provide example code?

@bachvudao, how would this work? The connection is released immediately. Callback are only needed for asynchronous operations. Please provide examples of how this works and what problem it solves.

@PeterNierop, what version of tedious-connection-pool are you using? This looks like a bug that was fixed last October.

Sorry for asking, How do I use that callback?  I am looking for something that allows me to catch the lost connection.

var Connection = require('tedious').Connection,
Request = require('tedious').Request,
TYPES = require('tedious').TYPES,
config = {
userName: 'sa',
password: 'as',
server: '172.16.252.90',
options : {
debug : {
packet : false,
data : false,
payload: false, //true,
token : false,
log : true
},
connectTimeout:5000,
database: 'test',
encrypt : false
}
},
runner = setInterval(() => {

    var connection = new Connection(config)
        .on('connect', (err) => {
            if (err) {
                console.error(err);
            } else {

                var request = new Request('hh.SomeStoredProcedure', (err) => {  
                    connection.close();
                    if (err) {
                        console.error(err);
                        return;
                    }
                }).on('returnValue', (parameterName, value, metadata) => {
                    console.log(parameterName + ' = ' + value.length);

                });

                var bin = new Buffer(8); 
                request.addParameter('iid', TYPES.Int, 1);
                request.addOutputParameter('res', TYPES.VarBinary, bin, {length: 8000});
                connection.callProcedure(request);
            }
        });
}, 1000);

Thank you

Shutting down the SQL server will invoke the same error.

@PeterNierop, please fix the formatting on your example. I'm not going to try to figure it out in it's current state.

To answer your question, you can catch errors by subscribing to the error event on the pool. The example main example in the README.md shows how to do this.

The err parameter of acquire only handled errors specifically related to acquiring the connection, not other connection errors (which can happen at anytime, event after acquiring).

Latest latest. That seems at least the case since I started this project in February. And I most certainly updated several times.

When you can, please use the website (rather than email) to post a clean example.

Hi @ben-page,

So my scenario is like this:

  1. I have a list of insert I'd like to execute. So I used the pool to execute them all. When all inserts are done, I would like to drain the pool.
  2. When each request finishes, I'd release the connection like below:
var request = new Request("....", function (err) {
            if (err) {
                logger.error("Error while inserting row: %s.", err);
            } else {
                logger.info("Finished request ");
            }

            connection.release();
            subject.next(0);
        });

The subject var is a Rx subject.

  1. To know when all my requests are done, I just subscribe to the Rx subject and drain the pool:
subject.take(requests.length).subscribe(
            function (x) { },
            function (err) { },
            function () {
                logger.info("Processed all %s requests. Closing connection pool.", requests.length);
                pool.drain();
            });

Doing this is giving me an error like below:

Tedious-Connection-Pool: draining pool
Tedious-Connection-Pool: connection ended: 40
Tedious-Connection-Pool: connection ended: 39
Tedious-Connection-Pool: connection ended: 38
Tedious-Connection-Pool: connection ended: 37
Tedious-Connection-Pool: connection ended: 36
Tedious-Connection-Pool: connection ended: 35
Tedious-Connection-Pool: connection ended: 34
Tedious-Connection-Pool: connection ended: 33
Tedious-Connection-Pool: connection ended: 32
Tedious-Connection-Pool: connection ended: 31
Tedious-Connection-Pool: connection ended: 30
Tedious-Connection-Pool: connection ended: 29
Tedious-Connection-Pool: connection ended: 28
Tedious-Connection-Pool: connection ended: 27
Tedious-Connection-Pool: connection ended: 26
Tedious-Connection-Pool: connection ended: 25
Tedious-Connection-Pool: connection ended: 24
Tedious-Connection-Pool: connection ended: 23
Tedious-Connection-Pool: connection ended: 22
Tedious-Connection-Pool: connection ended: 21
Tedious-Connection-Pool: connection ended: 20
Tedious-Connection-Pool: connection ended: 19
Tedious-Connection-Pool: connection ended: 18
Tedious-Connection-Pool: connection ended: 17
Tedious-Connection-Pool: connection ended: 16
Tedious-Connection-Pool: connection ended: 15
Tedious-Connection-Pool: connection ended: 14
Tedious-Connection-Pool: connection ended: 13
Tedious-Connection-Pool: connection ended: 12
Tedious-Connection-Pool: connection ended: 11
Tedious-Connection-Pool: connection ended: 10
Tedious-Connection-Pool: connection ended: 9
Tedious-Connection-Pool: connection ended: 8
Tedious-Connection-Pool: connection ended: 7
Tedious-Connection-Pool: connection ended: 6
Tedious-Connection-Pool: connection ended: 5
Tedious-Connection-Pool: connection ended: 4
Tedious-Connection-Pool: connection ended: 3
Tedious-Connection-Pool: connection ended: 2
Tedious-Connection-Pool: connection ended: 1
Tedious-Connection-Pool: connection closing because of error
2016-06-15 09:33:45.604 Could not connect to db ConnectionError: Connection lost - This socket is closed.

I think this error is because the pool is draining while some connection has not finished yet. By adding the callback, I can now do:

connection.release(function () {
                subject.next(0);
            });

The problem does go away for me after this. Let me know if you think there is a better way to do this.

@PeterNierop, your example doesn't seem to be using tedious-connection-pool at all. It's creating the connections directly.

I did fix a condition where TypeError: Cannot read property 'close' of undefined could be thrown. But I don't know if this solved your entire problem. If not, please post a complete example, including creating the pool, acquiring the connection, and releasing the connection.

@bachvudao, passing a callback to release() does nothing. It will never be executed.

We also saw this issue recently and it causes a server crash because the exception could not be handled. Will there be a new release of tedious-connection-pool that contains this fix?