async-queue.test.ts 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. import { ConnectionError, DataTypes, Model } from '@sequelize/core';
  2. import { Attribute, NotNull } from '@sequelize/core/decorators-legacy';
  3. import type { MsSqlConnection } from '@sequelize/mssql';
  4. import { AsyncQueueError } from '@sequelize/mssql';
  5. import { expect } from 'chai';
  6. import { beforeAll2, sequelize, setResetMode } from '../../support';
  7. describe('[MSSQL Specific] Async Queue', () => {
  8. if (!sequelize.dialect.name.startsWith('mssql')) {
  9. return;
  10. }
  11. setResetMode('none');
  12. const vars = beforeAll2(async () => {
  13. class User extends Model {
  14. @Attribute(DataTypes.STRING)
  15. @NotNull
  16. declare username: string;
  17. }
  18. sequelize.addModels([User]);
  19. await sequelize.sync({ force: true });
  20. await User.create({ username: 'John' });
  21. return { User };
  22. });
  23. it('should queue concurrent requests to a connection', async () => {
  24. await expect(
  25. sequelize.transaction(async transaction => {
  26. return Promise.all([
  27. vars.User.findOne({ transaction }),
  28. vars.User.findOne({ transaction }),
  29. ]);
  30. }),
  31. ).not.to.be.rejected;
  32. });
  33. it('requests that reject should not affect future requests', async () => {
  34. await expect(
  35. sequelize.transaction(async transaction => {
  36. await expect(vars.User.create({ username: new Date() })).to.be.rejected;
  37. await expect(vars.User.findOne({ transaction })).not.to.be.rejected;
  38. }),
  39. ).not.to.be.rejected;
  40. });
  41. it('closing the connection should reject pending requests', async () => {
  42. let promise;
  43. await expect(
  44. sequelize.transaction(async transaction => {
  45. promise = Promise.all([
  46. expect(sequelize.dialect.connectionManager.disconnect(transaction.getConnection())).to.be
  47. .fulfilled,
  48. expect(vars.User.findOne({ transaction }))
  49. .to.be.eventually.rejectedWith(
  50. ConnectionError,
  51. 'the connection was closed before this query could be executed',
  52. )
  53. .and.have.property('cause')
  54. .that.instanceOf(AsyncQueueError),
  55. expect(vars.User.findOne({ transaction }))
  56. .to.be.eventually.rejectedWith(
  57. ConnectionError,
  58. 'the connection was closed before this query could be executed',
  59. )
  60. .and.have.property('cause')
  61. .that.instanceOf(AsyncQueueError),
  62. ]);
  63. return promise;
  64. }),
  65. ).to.be.rejectedWith(
  66. ConnectionError,
  67. 'the connection was closed before this query could be executed',
  68. );
  69. await expect(promise).not.to.be.rejected;
  70. });
  71. it('closing the connection should reject in-progress requests', async () => {
  72. let promise;
  73. await expect(
  74. sequelize.transaction(async transaction => {
  75. const connection = transaction.getConnection() as MsSqlConnection;
  76. const wrappedExecSql = connection.execSql;
  77. connection.execSql = async function execSql(...args) {
  78. await sequelize.dialect.connectionManager.disconnect(connection);
  79. return wrappedExecSql.call(this, ...args);
  80. };
  81. promise = expect(vars.User.findOne({ transaction }))
  82. .to.be.eventually.rejectedWith(
  83. ConnectionError,
  84. 'the connection was closed before this query could finish executing',
  85. )
  86. .and.have.property('cause')
  87. .that.instanceOf(AsyncQueueError);
  88. return promise;
  89. }),
  90. )
  91. .to.be.eventually.rejectedWith(
  92. ConnectionError,
  93. 'the connection was closed before this query could be executed',
  94. )
  95. .and.have.property('cause')
  96. .that.instanceOf(AsyncQueueError);
  97. await expect(promise).not.to.be.rejected;
  98. });
  99. });