Skip to content

Commit 7055089

Browse files
committed
save local callsite and report it in promise rejection in case of error. Fixes #530
1 parent dc519bb commit 7055089

File tree

4 files changed

+165
-82
lines changed

4 files changed

+165
-82
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,14 +60,16 @@
6060
},
6161
"devDependencies": {
6262
"assert-diff": "^1.2.0",
63+
"error-stack-parser": "^2.0.1",
6364
"eslint": "^3.19.0",
6465
"eslint-config-prettier": "^2.1.1",
6566
"eslint-plugin-async-await": "0.0.0",
6667
"eslint-plugin-markdown": "^1.0.0-beta.2",
6768
"eslint-plugin-prettier": "^2.1.1",
6869
"husky": "^0.13.3",
69-
"portfinder": "^1.0.10",
70+
"is-async-supported": "^1.2.0",
7071
"lint-staged": "^3.4.2",
72+
"portfinder": "^1.0.10",
7173
"prettier": "^1.3.1",
7274
"prettier-markdown": "^0.1.6",
7375
"progress": "2.0.0",

promise.js

Lines changed: 101 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,78 @@ var EventEmitter = require('events').EventEmitter;
33
var util = require('util');
44

55
function inheritEvents(source, target, events) {
6-
events
7-
.forEach(function (eventName) {
8-
source.on(eventName, function () {
9-
var args = [].slice.call(arguments);
10-
args.unshift(eventName);
11-
12-
target.emit.apply(target, args);
13-
});
6+
events.forEach(function(eventName) {
7+
source.on(eventName, function() {
8+
var args = [].slice.call(arguments);
9+
args.unshift(eventName);
10+
11+
target.emit.apply(target, args);
1412
});
13+
});
1514
}
1615

17-
function createConnection (opts) {
18-
var coreConnection = core.createConnection(opts);
19-
var Promise = opts.Promise || global.Promise;
16+
function createConnection(opts) {
17+
const coreConnection = core.createConnection(opts);
18+
const createConnectionErr = new Error();
19+
const Promise = opts.Promise || global.Promise;
2020
if (!Promise) {
21-
throw new Error('no Promise implementation available.' +
22-
'Use promise-enabled node version or pass userland Promise' +
23-
' implementation as parameter, for example: { Promise: require(\'bluebird\') }');
21+
throw new Error(
22+
'no Promise implementation available.' +
23+
'Use promise-enabled node version or pass userland Promise' +
24+
" implementation as parameter, for example: { Promise: require('bluebird') }"
25+
);
2426
}
25-
return new Promise(function (resolve, reject) {
26-
coreConnection.once('connect', function (connectParams) {
27+
return new Promise(function(resolve, reject) {
28+
coreConnection.once('connect', function(connectParams) {
2729
resolve(new PromiseConnection(coreConnection, Promise));
2830
});
29-
coreConnection.once('error', reject);
31+
coreConnection.once('error', err => {
32+
createConnectionErr.message = err.message;
33+
createConnectionErr.code = err.code;
34+
createConnectionErr.errno = err.errno;
35+
createConnectionErr.sqlState = err.sqlState;
36+
reject(createConnectionErr);
37+
});
3038
});
3139
}
3240

33-
function PromiseConnection (connection, promiseImpl) {
41+
function PromiseConnection(connection, promiseImpl) {
3442
this.connection = connection;
3543
this.Promise = promiseImpl;
3644

37-
inheritEvents(connection, this, ['error', 'drain', 'connect', 'end', 'enqueue']);
45+
inheritEvents(connection, this, [
46+
'error',
47+
'drain',
48+
'connect',
49+
'end',
50+
'enqueue'
51+
]);
3852
}
3953
util.inherits(PromiseConnection, EventEmitter);
4054

41-
PromiseConnection.prototype.release = function () {
55+
PromiseConnection.prototype.release = function() {
4256
this.connection.release();
4357
};
4458

45-
function makeDoneCb (resolve, reject) {
46-
return function (err, rows, fields) {
59+
function makeDoneCb(resolve, reject, localErr) {
60+
return function(err, rows, fields) {
4761
if (err) {
48-
reject(err);
62+
localErr.message = err.message;
63+
localErr.code = err.code;
64+
localErr.errno = err.errno;
65+
localErr.sqlState = err.sqlState;
66+
reject(localErr);
4967
} else {
5068
resolve([rows, fields]);
5169
}
5270
};
5371
}
5472

55-
PromiseConnection.prototype.query = function (query, params) {
56-
var c = this.connection;
57-
return new this.Promise(function (resolve, reject) {
58-
var done = makeDoneCb(resolve, reject);
73+
PromiseConnection.prototype.query = function(query, params) {
74+
const c = this.connection;
75+
const localErr = new Error();
76+
return new this.Promise(function(resolve, reject) {
77+
const done = makeDoneCb(resolve, reject, localErr);
5978
if (params) {
6079
c.query(query, params, done);
6180
} else {
@@ -64,9 +83,9 @@ PromiseConnection.prototype.query = function (query, params) {
6483
});
6584
};
6685

67-
PromiseConnection.prototype.execute = function (query, params) {
86+
PromiseConnection.prototype.execute = function(query, params) {
6887
var c = this.connection;
69-
return new this.Promise(function (resolve, reject) {
88+
return new this.Promise(function(resolve, reject) {
7089
var done = makeDoneCb(resolve, reject);
7190
if (params) {
7291
c.execute(query, params, done);
@@ -76,50 +95,50 @@ PromiseConnection.prototype.execute = function (query, params) {
7695
});
7796
};
7897

79-
PromiseConnection.prototype.end = function () {
98+
PromiseConnection.prototype.end = function() {
8099
var c = this.connection;
81-
return new this.Promise(function (resolve, reject) {
82-
c.end(function () {
100+
return new this.Promise(function(resolve, reject) {
101+
c.end(function() {
83102
resolve();
84103
});
85104
});
86105
};
87106

88-
PromiseConnection.prototype.beginTransaction = function () {
107+
PromiseConnection.prototype.beginTransaction = function() {
89108
var c = this.connection;
90-
return new this.Promise(function (resolve, reject) {
109+
return new this.Promise(function(resolve, reject) {
91110
var done = makeDoneCb(resolve, reject);
92111
c.beginTransaction(done);
93112
});
94113
};
95114

96-
PromiseConnection.prototype.commit = function () {
115+
PromiseConnection.prototype.commit = function() {
97116
var c = this.connection;
98-
return new this.Promise(function (resolve, reject) {
117+
return new this.Promise(function(resolve, reject) {
99118
var done = makeDoneCb(resolve, reject);
100119
c.commit(done);
101120
});
102121
};
103122

104-
PromiseConnection.prototype.rollback = function () {
123+
PromiseConnection.prototype.rollback = function() {
105124
var c = this.connection;
106-
return new this.Promise(function (resolve, reject) {
125+
return new this.Promise(function(resolve, reject) {
107126
var done = makeDoneCb(resolve, reject);
108127
c.rollback(done);
109128
});
110129
};
111130

112-
PromiseConnection.prototype.ping = function () {
131+
PromiseConnection.prototype.ping = function() {
113132
var c = this.connection;
114-
return new this.Promise(function (resolve, reject) {
133+
return new this.Promise(function(resolve, reject) {
115134
c.ping(resolve);
116135
});
117136
};
118137

119-
PromiseConnection.prototype.connect = function () {
138+
PromiseConnection.prototype.connect = function() {
120139
var c = this.connection;
121-
return new this.Promise(function (resolve, reject) {
122-
c.connect(function (error, param) {
140+
return new this.Promise(function(resolve, reject) {
141+
c.connect(function(error, param) {
123142
if (error) {
124143
reject(error);
125144
} else {
@@ -129,29 +148,32 @@ PromiseConnection.prototype.connect = function () {
129148
});
130149
};
131150

132-
PromiseConnection.prototype.prepare = function (options) {
151+
PromiseConnection.prototype.prepare = function(options) {
133152
var c = this.connection;
134153
var promiseImpl = this.Promise;
135-
return new this.Promise(function (resolve, reject) {
136-
c.prepare(options, function (error, statement) {
154+
return new this.Promise(function(resolve, reject) {
155+
c.prepare(options, function(error, statement) {
137156
if (error) {
138157
reject(error);
139158
} else {
140-
var wrappedStatement = new PromisePreparedStatementInfo(statement, promiseImpl);
159+
var wrappedStatement = new PromisePreparedStatementInfo(
160+
statement,
161+
promiseImpl
162+
);
141163
resolve(wrappedStatement);
142164
}
143165
});
144166
});
145167
};
146168

147-
function PromisePreparedStatementInfo (statement, promiseImpl) {
169+
function PromisePreparedStatementInfo(statement, promiseImpl) {
148170
this.statement = statement;
149171
this.Promise = promiseImpl;
150172
}
151173

152-
PromisePreparedStatementInfo.prototype.execute = function (parameters) {
174+
PromisePreparedStatementInfo.prototype.execute = function(parameters) {
153175
var s = this.statement;
154-
return new this.Promise(function (resolve, reject) {
176+
return new this.Promise(function(resolve, reject) {
155177
var done = makeDoneCb(resolve, reject);
156178
if (parameters) {
157179
s.execute(parameters, done);
@@ -161,9 +183,9 @@ PromisePreparedStatementInfo.prototype.execute = function (parameters) {
161183
});
162184
};
163185

164-
PromisePreparedStatementInfo.prototype.close = function () {
186+
PromisePreparedStatementInfo.prototype.close = function() {
165187
var s = this.statement;
166-
return new this.Promise(function (resolve, reject) {
188+
return new this.Promise(function(resolve, reject) {
167189
s.close();
168190
resolve();
169191
});
@@ -177,26 +199,26 @@ PromisePreparedStatementInfo.prototype.close = function () {
177199
// implemented with PromiseConnection
178200

179201
// proxy synchronous functions only
180-
(function (functionsToWrap) {
181-
202+
(function(functionsToWrap) {
182203
for (var i = 0; functionsToWrap && i < functionsToWrap.length; i++) {
183204
var func = functionsToWrap[i];
184205

185206
if (
186-
typeof core.Connection.prototype[func] === 'function'
187-
&& PromiseConnection.prototype[func] === undefined
207+
typeof core.Connection.prototype[func] === 'function' &&
208+
PromiseConnection.prototype[func] === undefined
188209
) {
189-
PromiseConnection.prototype[func] = (function factory (funcName) {
190-
return function () {
191-
return core.Connection
192-
.prototype[funcName].apply(this.connection, arguments);
210+
PromiseConnection.prototype[func] = (function factory(funcName) {
211+
return function() {
212+
return core.Connection.prototype[funcName].apply(
213+
this.connection,
214+
arguments
215+
);
193216
};
194217
})(func);
195218
}
196219
}
197-
198220
})([
199-
// synchronous functions
221+
// synchronous functions
200222
'close',
201223
'createBinlogStream',
202224
'destroy',
@@ -212,16 +234,16 @@ PromisePreparedStatementInfo.prototype.close = function () {
212234
function PromisePool(pool, Promise) {
213235
this.pool = pool;
214236
this.Promise = Promise;
215-
237+
216238
inheritEvents(pool, this, ['acquire', 'connection', 'enqueue', 'release']);
217239
}
218240
util.inherits(PromisePool, EventEmitter);
219241

220-
PromisePool.prototype.getConnection = function () {
242+
PromisePool.prototype.getConnection = function() {
221243
var corePool = this.pool;
222244

223-
return new this.Promise(function (resolve, reject) {
224-
corePool.getConnection(function (err, coreConnection) {
245+
return new this.Promise(function(resolve, reject) {
246+
corePool.getConnection(function(err, coreConnection) {
225247
if (err) {
226248
reject(err);
227249
} else {
@@ -231,10 +253,10 @@ PromisePool.prototype.getConnection = function () {
231253
});
232254
};
233255

234-
PromisePool.prototype.query = function (sql, args) {
256+
PromisePool.prototype.query = function(sql, args) {
235257
var corePool = this.pool;
236258

237-
return new this.Promise(function (resolve, reject) {
259+
return new this.Promise(function(resolve, reject) {
238260
var done = makeDoneCb(resolve, reject);
239261
if (args) {
240262
corePool.query(sql, args, done);
@@ -244,19 +266,19 @@ PromisePool.prototype.query = function (sql, args) {
244266
});
245267
};
246268

247-
PromisePool.prototype.execute = function (sql, values) {
269+
PromisePool.prototype.execute = function(sql, values) {
248270
var corePool = this.pool;
249271

250-
return new Promise(function (resolve, reject) {
272+
return new Promise(function(resolve, reject) {
251273
corePool.execute(sql, values, makeDoneCb(resolve, reject));
252274
});
253275
};
254276

255-
PromisePool.prototype.end = function () {
277+
PromisePool.prototype.end = function() {
256278
var corePool = this.pool;
257279

258-
return new Promise(function (resolve, reject) {
259-
corePool.end(function (err) {
280+
return new Promise(function(resolve, reject) {
281+
corePool.end(function(err) {
260282
if (err) {
261283
reject(err);
262284
} else {
@@ -266,13 +288,15 @@ PromisePool.prototype.end = function () {
266288
});
267289
};
268290

269-
function createPool (opts) {
291+
function createPool(opts) {
270292
var corePool = core.createPool(opts);
271293
var Promise = opts.Promise || global.Promise;
272294
if (!Promise) {
273-
throw new Error('no Promise implementation available.' +
274-
'Use promise-enabled node version or pass userland Promise' +
275-
' implementation as parameter, for example: { Promise: require(\'bluebird\') }');
295+
throw new Error(
296+
'no Promise implementation available.' +
297+
'Use promise-enabled node version or pass userland Promise' +
298+
" implementation as parameter, for example: { Promise: require('bluebird') }"
299+
);
276300
}
277301

278302
return new PromisePool(corePool, Promise);

0 commit comments

Comments
 (0)