restify / clients

HttpClient, StringClient, and JsonClient extracted from restify
MIT License
57 stars 34 forks source link

client doesn't retry socket hang-up errors before response #162

Open hekike opened 6 years ago

hekike commented 6 years ago

COPIED: https://github.com/restify/node-restify/issues/483

The restify client doesn't retry socket hang-up errors that happen before a response is received. Here's a test program:

var mod_bunyan = require('bunyan');
var mod_fs = require('fs');
var mod_restify = require('restify');

var log, server, client, sockpath;

log = new mod_bunyan({
    'name': 'test',
    'level': process.env['LOG_LEVEL'] || 'info'
});

/* Clean up our UDS from an unclean shutdown. */
sockpath = '/tmp/mysock';
try {
        log.info('removing ', sockpath);
        mod_fs.unlinkSync(sockpath);
        log.info('removed ', sockpath);
} catch (ex) {
        if (ex['code'] != 'ENOENT')
                throw (ex);
        log.info('not found ', sockpath);
}

/*
 * Create a restify server that receives requests at /hello, waits 5 seconds,
 * and then closes the socket abruptly (before having sent any response).
 */
server = mod_restify.createServer();
server.get('/hello', function (req, res, next) {
        log.info('server: got request');
        req.socket.setTimeout(5000);

        /*
         * Close the client and server sockets 30 seconds after we receive the
         * first request so that our program exits.  This is just to demonstrate
         * that restify isn't actually retrying the request at this point.
         */
        setTimeout(function () {
                server.close();
                client.close();
        }, 30000);
});

/*
 * Start the server.  When it's ready, run the test case.
 */
server.listen(sockpath, function () {
        var rqoptions;

        log.info('server: listening');

        /*
         * Now that the server's up, create a restify client for the socket path
         * and submit a GET request to /hello.  We set the retry policy to 4
         * retries, but the restify client won't retry at all.
         */
        client = mod_restify.createStringClient({
            'socketPath': sockpath,
            'log': log,
            'version': '*'
        });

        rqoptions = {
            'path': '/hello',
            'retry': {
                'retries': 4,
                'minTimeout': 1000,
                'maxtimeout': 8000
            }
        };

        log.info('client: making request');
        client.get(rqoptions, function (err, req) {
                if (err) {
                        /*
                         * This is where the restify client reports an error --
                         * without having retried the request due to a socket
                         * hang-up.
                         */
                        log.error(err, 'client: error BEFORE request');
                        return;
                }

                log.info('client: request started');
                req.on('result', function (err2, res) {
                        if (err2) {
                                log.error(err2, 'client: error before response');
                                return;
                        }

                        log.info('client: response started');
                });
        });
});

Here's the output:

$ node -v
v0.8.26

$ time node test.js | bunyan
[2013-11-19T18:29:33.100Z]  INFO: test/34525 on bbc0462f: removing  /tmp/mysock
[2013-11-19T18:29:33.101Z]  INFO: test/34525 on bbc0462f: not found  /tmp/mysock
[2013-11-19T18:29:33.183Z]  INFO: test/34525 on bbc0462f: server: listening
[2013-11-19T18:29:33.202Z]  INFO: test/34525 on bbc0462f: client: making request
[2013-11-19T18:29:33.206Z]  INFO: test/34525 on bbc0462f: server: got request
[2013-11-19T18:29:38.208Z] ERROR: test/34525 on bbc0462f: client: error BEFORE request
    Error: socket hang up
        at createHangUpError (http.js:1379:15)
        at Socket.socketOnEnd (http.js:1476:23)
        at Pipe.onread (net.js:422:26)

real    0m30.312s
user    0m0.348s
sys     0m0.091s

Tried on restify 2.3.5, 2.6, and #master (9b07786060c240fcb1592289886d21d1f04c99c1).