有长字符串错误的序列化/繁琐的创建/更新记录:读取ECONNRESET

时间:2019-07-15 02:42:21

标签: node.js sql-server sequelize.js tedious

我正在尝试使用序列化/乏味性通过CRUD操作访问Azure SQL数据库。我在其中一张表中有一个长字符串(签名)。

CREATE TABLE [dbo].[Owner](
    [OwnerId] [int] PRIMARY KEY IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
    [Signature] [varchar](max) NULL
)

这是我的续集模型:

/* owner.js */
export default function(sequelize, DataTypes) {
  var Owner = sequelize.define(
    'Owner',
    {
      ownerId: {
        type: DataTypes.INTEGER,
        primaryKey: true,
        autoIncrement: true,
        allowNull: false,
        field: 'OwnerId',
      },
      name: {
        type: DataTypes.STRING(50),
        validate: {
          notEmpty: true,
        },
        allowNull: false,
        field: 'Name',
      },
      signature: {
        type: DataTypes.STRING(50000),
        validate: {
          notEmpty: true,
        },
        allowNull: true,
        field: 'Signature',
      },
    },
    {
      schema: 'dbo',
      timestamps: false,
      freezeTableName: true,
    }
  );

  return Owner;
}

这是读取和创建记录的代码:

/* index.js */
import Sequelize from 'sequelize';

var db = {};

var sequelize = new Sequelize('mydb', 'developer', 'mypassword', {
  host: 'mydevserver.database.windows.net',
  dialect: 'mssql',
  pool: {
    max: 5,
    min: 0,
    idle: 10000
  },
  dialectOptions: {
    options: {
      encrypt: true
    }
  }
});


db.sequelize = sequelize;
db.Sequelize = Sequelize;

var model = sequelize['import']('./owner.js');
db[model.name] = model;

/* Find a record with long signature (8000 chars) is fine. */
db.Owner.findByPk(6)
.then(o => {
  console.log(`Found owner ${o.name}, with signature ${o.signature}.`);
})

// let s = '0123456789'.repeat(100); /* This is ok. Record created. */
let s = '0123456789'.repeat(500); /* This gives error 'read ECONNRESET' */

db.Owner.create({  
  name: 'Rick',
  signature: `${s}`
})
.then(newOwner => {
  console.log(`New owner ${newOwner.name}, with id ${newOwner.ownerId} has been created.`);
}).catch(function (error) {
  console.log(error.message);
});

我正在使用

  "sequelize": "^5.10.1",
  "tedious": "^6.2.0"

我知道可以输入的字符串会有限制,但是5000字符的字符串并不长。

有什么想法吗?这是错误的堆栈跟踪

Unhandled rejection SequelizeDatabaseError: read ECONNRESET
    at Query.formatError (C:\work\GitRepos\sequelize-test\node_modules\sequelize\lib\dialects\mssql\query.js:309:12)
    at Request.userCallback (C:\work\GitRepos\sequelize-test\node_modules\sequelize\lib\dialects\mssql\query.js:69:23)
    at Request.callback (C:\work\GitRepos\sequelize-test\node_modules\tedious\lib\request.js:37:27)
    at Connection.socketError (C:\work\GitRepos\sequelize-test\node_modules\tedious\lib\connection.js:2157:20)
    at Connection.dispatchEvent (C:\work\GitRepos\sequelize-test\node_modules\tedious\lib\connection.js:1172:36)
    at Connection.socketError (C:\work\GitRepos\sequelize-test\node_modules\tedious\lib\connection.js:1190:10)
    at Socket.<anonymous> (C:\work\GitRepos\sequelize-test\node_modules\tedious\lib\connection.js:1032:14)
    at Socket.emit (events.js:205:15)
    at Socket.EventEmitter.emit (domain.js:471:20)
    at emitErrorNT (internal/streams/destroy.js:91:8)
    at emitErrorAndCloseNT (internal/streams/destroy.js:59:3)
    at processTicksAndRejections (internal/process/task_queues.js:84:9)

更新:

如果我增加了连接的数据包大小,

dialectOptions: {
    options: {
      encrypt: true,
      packetSize: 32768
    }
  }

然后问题解决了。即使我将字符串的长度增加到更大的数字,例如

let s = '0123456789'.repeat(500000);

它仍然有效。这对我来说没有意义。在服务器端,为什么当数据包大小为4096(默认值)时不重新组装数据包,但是在更大的数据包大小时,为什么要重新组装数据包。同样在客户端,无论包大小如何,都始终会重新组装包。


1 个答案:

答案 0 :(得分:0)

这似乎是Tedious中的bug,已在6.2.1中修复。当我在Azure中切换NodeJS应用程序以使用NodeJS 12时,我遇到了它。

上面提到的有关增加数据包大小的变通方法确实有效,这是我实现的,因为我正在使用Sequelize 4,并且不确定当前的Tedious版本是否兼容(我似​​乎记得在您需要某个版本的网络才能使Sequelize 4满意)。