hemerajs/hemera

HemeraError: Reply already sent

zllovesuki opened this issue · 4 comments

Description

HemeraError: Reply already sent is thrown for no apparent reasons

Steps to Reproduce

"worker" is connected with:

var connectTransport = function() {
    var nc = null
    return new Promise(function(resolve, reject) {
        nc = NATS.connect({
            noRandomize: true,
            urls: [
                'nats://endpoint:4222'
            ],
            tls: {
                ca: [ fs.readFileSync('ca.pem') ],
                cert: fs.readFileSync('client.pem'),
                key: fs.readFileSync('client-key.pem')
            },
            yieldTime: 50
        })
        nc.on('connect', function() {
            console.log('Connected to transport.')
            resolve(nc)
        })
        nc.on('error', function(e) {
            reject(e)
        })
    });
}

and is then used as:

connectTransport().then(function(transport) {

    var hemera = new Hemera(transport, {
        timeout: 5000,
        logLevel: 'warn',
        childLogger: true
    })

    hemera.use(HemeraJoi)

    hemera.ready().then(function() {

        /*          available       */

        hemera.add({
            topic: 'topic',
            cmd: 'cmd'
        }, function(req, cb) {

            // some database query, then cb(null, {ok: true, results: results})
        })

    })
})

then the request is served with hemera-web

Expected Result

  1. web api returns results
  2. no error/warn thrown in console

Actual Result

  1. web api returns results
  2. error/warn thrown in console
[2018-03-24T06:21:33.543Z] WARN (hemera-comm-wche84-lt.local-0b2e59852bfe47869aab284e15d83ed5/75360 on comm-wche84-lt.local): Reply already sent
    HemeraError: Reply already sent
        at Reply.send (/Users/rachel/dev/andromeda/application/node_modules/nats-hemera/lib/reply.js:100:21)
        at result.then.x (/Users/rachel/dev/andromeda/application/node_modules/nats-hemera/lib/index.js:851:37)
        at tryCatcher (/Users/rachel/dev/andromeda/application/node_modules/rethinkdb/node_modules/bluebird/js/main/util.js:26:23)
        at Promise._settlePromiseFromHandler (/Users/rachel/dev/andromeda/application/node_modules/rethinkdb/node_modules/bluebird/js/main/promise.js:510:31)
        at Promise._settlePromiseAt (/Users/rachel/dev/andromeda/application/node_modules/rethinkdb/node_modules/bluebird/js/main/promise.js:584:18)
        at Promise._settlePromises (/Users/rachel/dev/andromeda/application/node_modules/rethinkdb/node_modules/bluebird/js/main/promise.js:700:14)
        at Async._drainQueue (/Users/rachel/dev/andromeda/application/node_modules/rethinkdb/node_modules/bluebird/js/main/async.js:123:16)
        at Async._drainQueues (/Users/rachel/dev/andromeda/application/node_modules/rethinkdb/node_modules/bluebird/js/main/async.js:133:10)
        at Immediate.Async.drainQueues (/Users/rachel/dev/andromeda/application/node_modules/rethinkdb/node_modules/bluebird/js/main/async.js:15:14)
        at runCallback (timers.js:789:20)
        at tryOnImmediate (timers.js:751:5)
        at processImmediate [as _immediateCallback] (timers.js:722:5)

Context

  • nats-hemera (core)
  • hemera-web
  • hemera-joi

Your Environment

  • NATS: 1.0.4
  • Hemera (core): 5.0.0-rc.5
  • Hemera-web: 4.0.1
  • NodeJs: 8.9.4
  • Operating System and version: macOS 10.13.3

Interesting, in the function(req, cb) {} block, if I return a Promise, then it throws an Reply already sent.

Maybe you can add a check somewhere? So it's either callback style or Promise/async-await but not both?

Hi @zllovesuki did you miss some code? I can't see the code where you call the callback or return a promise. You can only use one style return a promise, callback or async / await.

You also don't have to wait for an established connection to NATS. Hemera does it for you.

const nc = NATS.connect({
  noRandomize: true,
  urls: ["nats://endpoint:4222"],
  tls: {
    ca: [fs.readFileSync("ca.pem")],
    cert: fs.readFileSync("client.pem"),
    key: fs.readFileSync("client-key.pem")
  },
  yieldTime: 50
});
const hemera = new Hemera(nc, {
  timeout: 5000,
  logLevel: "warn",
  childLogger: true
});
hemera.ready().then(function() { ...

I recommend you to read the docs about error-handling. Feel free to reopen.