Repository: luin/ioredis (ts)

Issue:
Unhandled rejection Error with multi/exec
If I set `dropBufferSupport` to `true`, I get the following error when running `exec`:

```
Unhandled rejection Error: *Buffer methods are not available because "dropBufferSupport" option is enabled.Refer to https://github.com/luin/ioredis/wiki/Improve-Performance for more details.
    at Pipeline.<anonymous> (/path/to/node_modules/ioredis/lib/commander.js:118:31)
    at Pipeline.exec (/path/to/node_modules/ioredis/lib/pipeline.js:203:23)
    at Pipeline.pipeline.exec (/path/to/node_modules/ioredis/lib/transaction.js:32:14)
    at /path/to/game/lib/server/RedisStore.js:37:12
    at tryCatcher (/path/to/node_modules/ioredis/node_modules/bluebird/js/release/util.js:16:23)
    at Promise.successAdapter [as _fulfillmentHandler0] (/path/to/node_modules/ioredis/node_modules/bluebird/js/release/nodeify.js:23:30)
    at Promise._settlePromise (/path/to/node_modules/ioredis/node_modules/bluebird/js/release/promise.js:556:21)
    at Promise._settlePromise0 (/path/to/node_modules/ioredis/node_modules/bluebird/js/release/promise.js:604:10)
    at Promise._settlePromises (/path/to/node_modules/ioredis/node_modules/bluebird/js/release/promise.js:683:18)
    at Async._drainQueue (/path/to/node_modules/ioredis/node_modules/bluebird/js/release/async.js:138:16)
    at Async._drainQueues (/path/to/node_modules/ioredis/node_modules/bluebird/js/release/async.js:148:10)
    at Immediate.Async.drainQueues [as _onImmediate] (/path/to/node_modules/ioredis/node_modules/bluebird/js/release/async.js:17:14)
    at processImmediate [as _immediateCallback] (timers.js:383:17)
```

No `buffer` methods are being called, so why am I seeing this error?

```javascript
redis.multi()
    .srem('set1', reply)
    .srem('set2', reply)
    .srem('set3', reply)
    .srem('set4', reply)
    .srem('set5', reply)
    .exec();
```

Pull request description:
fix transaction with dropBufferSupport:true
fixes #313 + regression test.

@luin There is another issue now with `dropBufferSupport` regarding transactions that combine both Buffer & non-Buffer methods.
I'm not sure this is supported now and will cause an error.


Patch:
diff --git a/lib/pipeline.js b/lib/pipeline.js
index 436775e..2f35922 100644
--- a/lib/pipeline.js
+++ b/lib/pipeline.js
@@ -190,6 +190,7 @@ Pipeline.prototype.multi = function () {
 };
 
 var execBuffer = Pipeline.prototype.execBuffer;
+var exec = Pipeline.prototype.exec;
 Pipeline.prototype.execBuffer = util.deprecate(function () {
   if (this._transactions > 0) {
     this._transactions -= 1;
@@ -200,7 +201,7 @@ Pipeline.prototype.execBuffer = util.deprecate(function () {
 Pipeline.prototype.exec = function (callback) {
   if (this._transactions > 0) {
     this._transactions -= 1;
-    return execBuffer.apply(this, arguments);
+    return (this.options.dropBufferSupport ? exec : execBuffer).apply(this, arguments);
   }
   if (!this.nodeifiedPromise) {
     this.nodeifiedPromise = true;


Test patch:
diff --git a/test/functional/drop_buffer_support.js b/test/functional/drop_buffer_support.js
index f8fd92b..7ea2247 100644
--- a/test/functional/drop_buffer_support.js
+++ b/test/functional/drop_buffer_support.js
@@ -84,16 +84,44 @@ describe('dropBufferSupport', function () {
         expect(err).to.eql(null);
         expect(res[0][1]).to.eql('OK');
         expect(res[1][1]).to.eql('bar');
+        redis.disconnect();
         done();
       });
     });
 
+    it('should work with transaction', function (done) {
+      var redis = new Redis({ dropBufferSupport: true });
+      redis.multi()
+        .set('foo', 'bar')
+        .get('foo')
+        .exec(function(err, res) {
+          expect(err).to.eql(null);
+          expect(res[0][1]).to.eql('OK');
+          expect(res[1][1]).to.eql('bar');
+          redis.disconnect();
+          done();
+        });
+    });
+
+    it('should fail early with Buffer transaction', function (done) {
+      var redis = new Redis({ dropBufferSupport: true });
+      redis.multi()
+        .set('foo', 'bar')
+        .getBuffer(new Buffer('foo'), function(err) {
+          expect(err.message).to.match(/Buffer methods are not available/);
+          redis.disconnect();
+          done();
+        });
+    });
+
     it('should work with internal select command', function (done) {
       var redis = new Redis({ dropBufferSupport: true, db: 1 });
       var check = new Redis({ db: 1 });
       redis.set('foo', 'bar', function () {
         check.get('foo', function (err, res) {
           expect(res).to.eql('bar');
+          redis.disconnect();
+          check.disconnect();
           done();
         });
       });