From bbfd2fc3572b6d9dd2d7173b6a6c401acb8505bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=90=E9=AA=85?= Date: Sat, 8 Jun 2019 21:31:20 +0800 Subject: [PATCH] fix: pipeline with transactions causes unhandled warnings (#884) Pipeline#exec() is a little tricky: it has a init process when called first time (indicated by whether Pipeline#nodeifiedPromise is true). Transaction#exec() is similar to that, it has a init process that parse the result from Pipeline#exec before returning to users. However, #nodeifiedPromise is not checked here. Closes: #883 --- lib/transaction.ts | 6 ++++ test/functional/cluster/transaction.js | 42 ++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/lib/transaction.ts b/lib/transaction.ts index a881ff9c..1c3f383d 100644 --- a/lib/transaction.ts +++ b/lib/transaction.ts @@ -31,6 +31,12 @@ export function addTransactionSupport (redis) { if (this._transactions > 0) { exec.call(pipeline) } + + // Returns directly when the pipeline + // has been called multiple times (retries). + if (this.nodeifiedPromise) { + return exec.call(pipeline) + } const promise = exec.call(pipeline) return asCallback(promise.then(function (result) { const execResult = result[result.length - 1] diff --git a/test/functional/cluster/transaction.js b/test/functional/cluster/transaction.js index 5864be0c..70e21832 100644 --- a/test/functional/cluster/transaction.js +++ b/test/functional/cluster/transaction.js @@ -36,6 +36,7 @@ describe('cluster:transaction', function () { var cluster = new Redis.Cluster([ { host: '127.0.0.1', port: '30001' } ]); + cluster.multi().get('foo').set('foo', 'bar').exec(function (err, result) { expect(err).to.eql(null); expect(result[0]).to.eql([null, 'bar']); @@ -97,4 +98,45 @@ describe('cluster:transaction', function () { done(); }); }); + + it('should not print unhandled warnings', function (done) { + const errorMessage = 'Connection is closed.' + var slotTable = [ + [0, 16383, ['127.0.0.1', 30001]] + ]; + new MockServer(30001, function (argv) { + if (argv[0] === 'exec' || argv[1] === 'foo') { + return new Error(errorMessage) + } + }, slotTable); + + var cluster = new Redis.Cluster([ + { host: '127.0.0.1', port: '30001' } + ], { + maxRedirections: 3 + }); + + let isDoneCalled = false + const wrapDone = function (error) { + if (isDoneCalled) { + return + } + isDoneCalled = true + process.removeAllListeners('unhandledRejection') + done(error) + } + + process.on('unhandledRejection', err => { + wrapDone(new Error('got unhandledRejection: ' + err.message)) + }) + cluster.multi().get('foo').set('foo', 'bar').exec(function (err) { + expect(err).to.have.property('message', errorMessage) + cluster.on('end', function () { + // Wait for the end event to ensure the transaction + // promise has been resolved. + wrapDone(); + }) + cluster.disconnect(); + }); + }); });