Bluebird 在与 Sequelize/MySQL 一起使用时显示损坏的堆栈跟踪

Bluebird shows broken stacktrace when using with Sequelize/MySQL

本文关键字:显示 损坏 跟踪 堆栈 Sequelize 在与 MySQL 一起 Bluebird      更新时间:2023-09-26

我在Node上使用bluebird promises和Sequelize(内部也使用bluebird)。

一开始我就这样做:

// only use one Promise library for the entire application
GLOBAL.Promise = Sequelize.Promise || require('bluebird');
// setup long stack traces
GLOBAL.Promise.longStackTraces();

大多数时候,我都会得到精细的堆栈跟踪。但有时当我从 Sequelize 的底层 MySQL 实现中收到错误时,堆栈跟踪会出错,如下所示:

SequelizeUniqueConstraintError
    at module.exports.Query.formatError (D:'code'theapp'node_modules'sequelize'lib'dialects'mysql'query.js:109:16)
    at Query._callback (D:'code'theapp'node_modules'sequelize'lib'dialects'mysql'query.js:38:23)
    at Query.Sequence.end (D:'code'theapp'node_modules'mysql'lib'protocol'sequences'Sequence.js:96:24)
    at Query.ErrorPacket (D:'code'theapp'node_modules'mysql'lib'protocol'sequences'Query.js:93:8)
    at Protocol._parsePacket (D:'code'theapp'node_modules'mysql'lib'protocol'Protocol.js:271:23)
    at Parser.write (D:'code'theapp'node_modules'mysql'lib'protocol'Parser.js:77:12)
    at Protocol.write (D:'code'theapp'node_modules'mysql'lib'protocol'Protocol.js:39:16)
    at Socket.<anonymous    (D:'code'theapp'node_modules'mysql'lib'Connection.js:82:28)
    at Socket.emit (events.js:95:17)
    at Socket.<anonymous    (_stream_readable.js:764:14)
    at Socket.emit (events.js:92:17)
    at emitReadable_ (_stream_readable.js:426:10)
    at emitReadable (_stream_readable.js:422:5)
    at readableAddChunk (_stream_readable.js:165:9) 
From previous event:
From previous event:
From previous event:
From previous event:
From previous event:
From previous event:
From previous event:
From previous event:
From previous event:
From previous event:
From previous event:
From previous event:
From previous event: (D:/code/theapp/components/util/Log.js:116)

我在Windows 7上运行Node v0.10.33。

这是一个错误吗?如果是这样,我应该用哪个库(或 Node?)提交它?

我做了更多的挖掘,发现这个特定的错误是一个自定义的Sequelize错误,在它的构造函数中,调用了进一步的自定义错误构造函数,一直到Error.apply(this, arguments)。此错误还会包装原始错误。如果我获得的不是包装器,而是本机错误(不是通过 Error.apply 创建的),即使我只读取一次(如 var smth = err.theWrappedError && err.theWrappedError.something;),也会出现正确的堆栈跟踪。所以我认为,这和之前的堆栈跟踪之谜一样,可能是一个 V8 错误。

作为参考,这段代码导致了上面的错误堆栈跟踪:

if (!message) {
    message = 'exception';
}
console.error(message = this.Tools.formatUserMessage((message && (message + ' - ') || '')));
console.error(err.stack);

此代码显示更多信息和正确的堆栈跟踪:

var parent = err.parent;    // access the underlying error here
var sql = (parent && parent.sql) || err.sql;
var sqlMessage = sql && 'SQL error `' + sql + ']';
if (!message) {
    if (sql) {
        message = sqlMessage;
    }
    else {
        message = 'exception';
    }
}
else {
    message += ' - ' + sqlMessage;
}
console.error(message = this.Tools.formatUserMessage((message && (message + ' - ') || '')));
console.error(err.stack);
parent && parent.stack && console.error(parent.stack);

两件事:

  1. 最终,你可能想让它完全递归,只要有另一个parent,就继续上升,即使我还没有看到超过两个的错误链。
  2. 即使正确的错误跟踪将由err.stack显示,显示整个事情也不会有什么坏处。

第二个代码片段中的堆栈跟踪示例:

[2015-01-30 17:09:13.235] [ERROR] default - [asd] SQL error (`INSERT INTO `theApp_user` (`uid`,`role`,`displayRole`,`name`,`locale`,`createdAt`,`updatedAt`) VALUES (DEFAULT,4,4,'asd','en','20109:13','2015-01-30 09:09:13');`) -  (D:/code/theApp/components/util/Log.js:126)
[2015-01-30 17:09:13.237] [ERROR] default - SequelizeUniqueConstraintError
    at module.exports.Query.formatError (D:'code'theApp'node_modules'sequelize'lib'dialects'mysql'query.js:109:16)
    at Query._callback (D:'code'theApp'node_modules'sequelize'lib'dialects'mysql'query.js:38:23)
    at Query.Sequence.end (D:'code'theApp'node_modules'mysql'lib'protocol'sequences'Sequence.js:96:24)
    at Query.ErrorPacket (D:'code'theApp'node_modules'mysql'lib'protocol'sequences'Query.js:93:8)
    at Protocol._parsePacket (D:'code'theApp'node_modules'mysql'lib'protocol'Protocol.js:271:23)
    at Parser.write (D:'code'theApp'node_modules'mysql'lib'protocol'Parser.js:77:12)
    at Protocol.write (D:'code'theApp'node_modules'mysql'lib'protocol'Protocol.js:39:16)
    at Socket.<anonymous> (D:'code'theApp'node_modules'mysql'lib'Connection.js:82:28)
    at Socket.emit (events.js:95:17)
    at Socket.<anonymous> (_stream_readable.js:764:14)
    at Socket.emit (events.js:92:17)
    at emitReadable_ (_stream_readable.js:426:10)
    at emitReadable (_stream_readable.js:422:5)
    at readableAddChunk (_stream_readable.js:165:9)
From previous event:
    at new Promise (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:84:37)
    at new SequelizePromise (D:'code'theApp'node_modules'sequelize'lib'promise.js:28:17)
    at module.exports.Query.run (D:'code'theApp'node_modules'sequelize'lib'dialects'mysql'query.js:31:19)
    at D:'code'theApp'node_modules'sequelize'lib'sequelize.js:613:20
    at Promise._settlePromiseAt (D:'code'theApp'node_modules'sequelize'lib'promise.js:66:18)
    at process._tickDomainCallback (node.js:463:13)
From previous event:
    at new Promise (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:84:37)
    at new SequelizePromise (D:'code'theApp'node_modules'sequelize'lib'promise.js:28:17)
    at ConnectionManager.getConnection (D:'code'theApp'node_modules'sequelize'lib'dialects'abstract'connection-manager.js:186:10)
    at module.exports.Sequelize.query (D:'code'theApp'node_modules'sequelize'lib'sequelize.js:610:85)
    at module.exports.QueryInterface.insert (D:'code'theApp'node_modules'sequelize'lib'query-interface.js:451:27)
    at D:'code'theApp'node_modules'sequelize'lib'instance.js:601:43
From previous event:
    at D:'code'theApp'node_modules'sequelize'lib'instance.js:578:25
    at Promise._settlePromiseAt (D:'code'theApp'node_modules'sequelize'lib'promise.js:66:18)
    at process._tickDomainCallback (node.js:463:13)
From previous event:
    at module.exports.Instance.save (D:'code'theApp'node_modules'sequelize'lib'instance.js:500:23)
    at module.exports.Model.create (D:'code'theApp'node_modules'sequelize'lib'model.js:1051:8)
    at Object.Private.createAndLogin (D:'code'theApp'components'models'core'User.js:339:38)
    at Object.<anonymous> (D:'code'theApp'components'debug'CourseSimulator.js:440:55)
From previous event:
    at Object.<anonymous> (D:'code'theApp'components'debug'CourseSimulator.js:415:47)
    at Promise._settlePromiseAt (D:'code'theApp'node_modules'sequelize'lib'promise.js:66:18)
From previous event:
    at Promise$bind [as bind] (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:104:9)
    at Object.Public.reset (D:'code'theApp'components'debug'CourseSimulator.js:390:22)
    at D:'code'theApp'node_modules'nogap'lib'CommandProxy.js:129:74
    at tryCatcher (D:'code'theApp'node_modules'nogap'assets'bluebird.js:4408:31)
    at Promise._settlePromiseFromHandler (D:'code'theApp'node_modules'nogap'assets'bluebird.js:2342:31)
    at Promise._settlePromiseAt (D:'code'theApp'node_modules'nogap'assets'bluebird.js:2504:18)
    at Promise._settlePromiseAtPostResolution (D:'code'theApp'node_modules'nogap'assets'bluebird.js:2070:10)
    at Async._drainQueue (D:'code'theApp'node_modules'nogap'assets'bluebird.js:152:12)
    at Async._drainQueues (D:'code'theApp'node_modules'nogap'assets'bluebird.js:157:10)
    at Async.drainQueues (D:'code'theApp'node_modules'nogap'assets'bluebird.js:82:14)
    at process._tickDomainCallback (node.js:463:13)
From previous event:
    at new Promise (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:84:37)
    at new SequelizePromise (D:'code'theApp'node_modules'sequelize'lib'promise.js:28:17)
    at ConnectionManager.releaseConnection (D:'code'theApp'node_modules'sequelize'lib'dialects'abstract'connection-manager.js:196:10)
    at D:'code'theApp'node_modules'sequelize'lib'sequelize.js:615:39
    at Object.finallyHandler (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'finally.js:64:23)
From previous event:
    at new Promise (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:84:37)
    at new SequelizePromise (D:'code'theApp'node_modules'sequelize'lib'promise.js:28:17)
    at module.exports.Query.run (D:'code'theApp'node_modules'sequelize'lib'dialects'mysql'query.js:31:19)
    at D:'code'theApp'node_modules'sequelize'lib'sequelize.js:613:20
    at Promise._settlePromiseAt (D:'code'theApp'node_modules'sequelize'lib'promise.js:66:18)
    at process._tickDomainCallback (node.js:463:13)
From previous event:
    at new Promise (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:84:37)
    at new SequelizePromise (D:'code'theApp'node_modules'sequelize'lib'promise.js:28:17)
    at ConnectionManager.getConnection (D:'code'theApp'node_modules'sequelize'lib'dialects'abstract'connection-manager.js:186:10)
    at module.exports.Sequelize.query (D:'code'theApp'node_modules'sequelize'lib'sequelize.js:610:85)
    at module.exports.QueryInterface.insert (D:'code'theApp'node_modules'sequelize'lib'query-interface.js:451:27)
    at D:'code'theApp'node_modules'sequelize'lib'instance.js:601:43
From previous event:
    at D:'code'theApp'node_modules'sequelize'lib'instance.js:578:25
    at Promise._settlePromiseAt (D:'code'theApp'node_modules'sequelize'lib'promise.js:66:18)
    at process._tickDomainCallback (node.js:463:13)
From previous event:
    at module.exports.Instance.save (D:'code'theApp'node_modules'sequelize'lib'instance.js:500:23)
    at module.exports.Model.create (D:'code'theApp'node_modules'sequelize'lib'model.js:1051:8)
    at Object.Private.createAndLogin (D:'code'theApp'components'models'core'User.js:339:38)
    at Object.<anonymous> (D:'code'theApp'components'debug'CourseSimulator.js:440:55)
From previous event:
    at Object.<anonymous> (D:'code'theApp'components'debug'CourseSimulator.js:415:47)
    at Promise._settlePromiseAt (D:'code'theApp'node_modules'sequelize'lib'promise.js:66:18)
From previous event:
    at Promise$bind [as bind] (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:104:9)
    at Object.Public.reset (D:'code'theApp'components'debug'CourseSimulator.js:390:22)
    at D:'code'theApp'node_modules'nogap'lib'CommandProxy.js:129:74
    at tryCatcher (D:'code'theApp'node_modules'nogap'assets'bluebird.js:4408:31)
    at Promise._settlePromiseFromHandler (D:'code'theApp'node_modules'nogap'assets'bluebird.js:2342:31)
    at Promise._settlePromiseAt (D:'code'theApp'node_modules'nogap'assets'bluebird.js:2504:18)
    at Promise._settlePromiseAtPostResolution (D:'code'theApp'node_modules'nogap'assets'bluebird.js:2070:10)
    at Async._drainQueue (D:'code'theApp'node_modules'nogap'assets'bluebird.js:152:12)
    at Async._drainQueues (D:'code'theApp'node_modules'nogap'assets'bluebird.js:157:10)
    at Async.drainQueues (D:'code'theApp'node_modules'nogap'assets'bluebird.js:82:14)
    at process._tickDomainCallback (node.js:463:13) (D:/code/theApp/components/util/Log.js:127)
[2015-01-30 17:09:13.240] [ERROR] default - Error: ER_DUP_ENTRY: Duplicate entry 'asd' for key 'theApp_user_name'
    at Query.Sequence._packetToError (D:'code'theApp'node_modules'mysql'lib'protocol'sequences'Sequence.js:48:14)
    at Query.ErrorPacket (D:'code'theApp'node_modules'mysql'lib'protocol'sequences'Query.js:82:18)
    at Protocol._parsePacket (D:'code'theApp'node_modules'mysql'lib'protocol'Protocol.js:271:23)
    at Parser.write (D:'code'theApp'node_modules'mysql'lib'protocol'Parser.js:77:12)
    at Protocol.write (D:'code'theApp'node_modules'mysql'lib'protocol'Protocol.js:39:16)
    at Socket.<anonymous> (D:'code'theApp'node_modules'mysql'lib'Connection.js:82:28)
    at Socket.emit (events.js:95:17)
    at Socket.<anonymous> (_stream_readable.js:764:14)
    at Socket.emit (events.js:92:17)
    at emitReadable_ (_stream_readable.js:426:10)
    at emitReadable (_stream_readable.js:422:5)
    at readableAddChunk (_stream_readable.js:165:9)
    at Socket.Readable.push (_stream_readable.js:127:10)
    at TCP.onread (net.js:528:21)
    --------------------
    at Protocol._enqueue (D:'code'theApp'node_modules'mysql'lib'protocol'Protocol.js:135:48)
    at Connection.query (D:'code'theApp'node_modules'mysql'lib'Connection.js:185:25)
    at D:'code'theApp'node_modules'sequelize'lib'dialects'mysql'query.js:32:23
    at sequelizeResolver (D:'code'theApp'node_modules'sequelize'lib'promise.js:32:12)
    at tryCatch2 (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'util.js:53:21)
    at Promise$_resolveFromResolver [as _resolveFromResolver] (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:618:13)
    at new Promise (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:84:37)
    at new SequelizePromise (D:'code'theApp'node_modules'sequelize'lib'promise.js:28:17)
    at module.exports.Query.run (D:'code'theApp'node_modules'sequelize'lib'dialects'mysql'query.js:31:19)
    at D:'code'theApp'node_modules'sequelize'lib'sequelize.js:613:20
    at tryCatch1 (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'util.js:45:21)
    at Promise$_callHandler [as _callHandler] (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:660:13)
    at Promise$_settlePromiseFromHandler [as _settlePromiseFromHandler] (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:675:18)
    at Promise$_settlePromiseAt (D:'code'theApp'node_modules'sequelize'node_modules'bluebird'js'main'promise.js:845:14)
    at Promise._settlePromiseAt (D:'code'theApp'node_modules'sequelize'lib'promise.js:66:18) (D:/code/theApp/components/util/Log.js:128)

更新

实际上我发现有时可以工作,有时

不会,有时可以部分工作(显示部分堆栈跟踪)...也许是 V8 堆栈或堆管理器中的竞争条件......