diff --git a/src/model-internals.ts b/src/model-internals.ts index bc960f8421c8..2d6137dbdc75 100644 --- a/src/model-internals.ts +++ b/src/model-internals.ts @@ -148,9 +148,9 @@ export function throwInvalidInclude(include: any): never { Got ${NodeUtil.inspect(include)} instead`); } -export function setTransactionFromAls(options: Transactionable, sequelize: Sequelize): void { +export function setTransactionFromCls(options: Transactionable, sequelize: Sequelize): void { if (options.transaction === undefined) { - options.transaction = sequelize.getCurrentAlsTransaction(); + options.transaction = sequelize.getCurrentClsTransaction(); } } diff --git a/src/model.d.ts b/src/model.d.ts index 84200062acfa..2bc0dca3ae7b 100644 --- a/src/model.d.ts +++ b/src/model.d.ts @@ -66,7 +66,7 @@ export interface Transactionable { /** * The transaction in which this query must be run. * - * If {@link Options.disableAlsTransactions} has not been set to true, and a transaction is running in the current ALS context, + * If {@link Options.disableClsTransactions} has not been set to true, and a transaction is running in the current AsyncLocalStorage context, * that transaction will be used, unless null or a Transaction is manually specified here. */ transaction?: Transaction | null | undefined; diff --git a/src/model.js b/src/model.js index 42d8d5445acd..1ebb9d4e692e 100644 --- a/src/model.js +++ b/src/model.js @@ -31,7 +31,7 @@ const { QueryTypes } = require('./query-types'); const sequelizeErrors = require('./errors'); const DataTypes = require('./data-types'); const { Op } = require('./operators'); -const { _validateIncludedElements, combineIncludes, throwInvalidInclude, setTransactionFromAls } = require('./model-internals'); +const { _validateIncludedElements, combineIncludes, throwInvalidInclude, setTransactionFromCls } = require('./model-internals'); const { noDoubleNestedGroup, scopeRenamedToWithScope, schemaRenamedToWithSchema, noModelDropSchema } = require('./utils/deprecations'); // This list will quickly become dated, but failing to maintain this list just means @@ -1195,7 +1195,7 @@ ${associationOwner._getAssociationDebugList()}`); tableNames[this.getTableName(options)] = true; options = cloneDeep(options); - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); _.defaults(options, { hooks: true, model: this }); @@ -1512,7 +1512,7 @@ ${associationOwner._getAssociationDebugList()}`); options = cloneDeep(options); options = _.defaults(options, { hooks: true }); - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); options.raw = true; if (options.hooks) { @@ -1793,7 +1793,7 @@ ${associationOwner._getAssociationDebugList()}`); } } - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); const internalTransaction = !options.transaction; let values; @@ -1954,7 +1954,7 @@ ${associationOwner._getAssociationDebugList()}`); ...cloneDeep(options), }; - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); const modelDefinition = this.modelDefinition; @@ -2061,7 +2061,7 @@ ${associationOwner._getAssociationDebugList()}`); const now = new Date(); options = cloneDeep(options); - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); options.model = this; @@ -2424,7 +2424,7 @@ ${associationOwner._getAssociationDebugList()}`); static async destroy(options) { options = cloneDeep(options); - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); this._injectScope(options); @@ -2523,7 +2523,7 @@ ${associationOwner._getAssociationDebugList()}`); ...options, }; - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); options.type = QueryTypes.RAW; options.model = this; @@ -2586,7 +2586,7 @@ ${associationOwner._getAssociationDebugList()}`); static async update(values, options) { options = cloneDeep(options); - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); this._injectScope(options); this._optionsMustContainWhere(options); @@ -3515,7 +3515,7 @@ Instead of specifying a Model, either: validate: true, }); - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); const modelDefinition = this.constructor.modelDefinition; @@ -3896,7 +3896,7 @@ Instead of specifying a Model, either: ...options, }; - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); const modelDefinition = this.constructor.modelDefinition; @@ -3979,7 +3979,7 @@ Instead of specifying a Model, either: ...options, }; - setTransactionFromAls(options, this.sequelize); + setTransactionFromCls(options, this.sequelize); // Run before hook if (options.hooks) { diff --git a/src/sequelize-typescript.ts b/src/sequelize-typescript.ts index 1054e23085cb..9b4d7679a673 100644 --- a/src/sequelize-typescript.ts +++ b/src/sequelize-typescript.ts @@ -177,10 +177,10 @@ export abstract class SequelizeTypeScript { beforeAssociate = legacyBuildAddHook(instanceSequelizeHooks, 'beforeAssociate'); afterAssociate = legacyBuildAddHook(instanceSequelizeHooks, 'afterAssociate'); - #transactionAls: AsyncLocalStorage | undefined; + #transactionCls: AsyncLocalStorage | undefined; - private _setupTransactionAls() { - this.#transactionAls = new AsyncLocalStorage(); + private _setupTransactionCls() { + this.#transactionCls = new AsyncLocalStorage(); } addModels(models: ModelStatic[]) { @@ -198,10 +198,10 @@ export abstract class SequelizeTypeScript { /** * Returns the transaction that is associated to the current asynchronous operation. * This method returns undefined if no transaction is active in the current asynchronous operation, - * or if {@link Options.disableAlsTransactions} is true. + * or if {@link Options.disableClsTransactions} is true. */ - getCurrentAlsTransaction(): Transaction | undefined { - return this.#transactionAls?.getStore(); + getCurrentClsTransaction(): Transaction | undefined { + return this.#transactionCls?.getStore(); } /** @@ -222,12 +222,12 @@ export abstract class SequelizeTypeScript { * ``` * * By default, Sequelize uses AsyncLocalStorage to automatically pass the transaction to all queries executed inside the callback (unless you already pass one or set the `transaction` option to null). - * This can be disabled by setting {@link Options.disableAlsTransactions} to true. You will then need to pass transactions to your queries manually. + * This can be disabled by setting {@link Options.disableClsTransactions} to true. You will then need to pass transactions to your queries manually. * * ```ts * const sequelize = new Sequelize({ * // ... - * disableAlsTransactions: true, + * disableClsTransactions: true, * }) * * await sequelize.transaction(transaction => { @@ -292,12 +292,12 @@ export abstract class SequelizeTypeScript { return result; }; - const als = this.#transactionAls; - if (!als) { + const cls = this.#transactionCls; + if (!cls) { return wrappedCallback(); } - return als.run(transaction, wrappedCallback); + return cls.run(transaction, wrappedCallback); } /** @@ -305,7 +305,7 @@ export abstract class SequelizeTypeScript { * If you really want to use the manual solution, don't forget to commit or rollback your transaction once you are done with it. * * Transactions started by this method are not automatically passed to queries. You must pass the transaction object manually, - * even if {@link Options.disableAlsTransactions} is false. + * even if {@link Options.disableClsTransactions} is false. * * @example * ```ts diff --git a/src/sequelize.d.ts b/src/sequelize.d.ts index c33a82383aff..3f5460d22640 100644 --- a/src/sequelize.d.ts +++ b/src/sequelize.d.ts @@ -453,10 +453,10 @@ export interface Options extends Logging { * Disable the use of AsyncLocalStorage to automatically pass transactions started by {@link Sequelize#transaction}. * You will need to pass transactions around manually if you disable this. */ - disableAlsTransactions?: boolean; + disableClsTransactions?: boolean; } -export interface NormalizedOptions extends PartlyRequired { +export interface NormalizedOptions extends PartlyRequired { readonly replication: NormalizedReplicationOptions; } diff --git a/src/sequelize.js b/src/sequelize.js index 43cf7d4499bd..b457ef8b813a 100644 --- a/src/sequelize.js +++ b/src/sequelize.js @@ -258,7 +258,7 @@ export class Sequelize extends SequelizeTypeScript { benchmark: false, minifyAliases: false, logQueryParameters: false, - disableAlsTransactions: false, + disableClsTransactions: false, ...options, pool: _.defaults(options.pool || {}, { max: 5, @@ -270,8 +270,8 @@ export class Sequelize extends SequelizeTypeScript { }; // TODO: remove & assign property directly once this constructor has been migrated to the SequelizeTypeScript class - if (!this.options.disableAlsTransactions) { - this._setupTransactionAls(); + if (!this.options.disableClsTransactions) { + this._setupTransactionCls(); } if (!this.options.dialect) { @@ -695,7 +695,7 @@ Use Sequelize#query if you wish to use replacements.`); return await retry(async () => { if (options.transaction === undefined) { - options.transaction = this.getCurrentAlsTransaction(); + options.transaction = this.getCurrentClsTransaction(); } checkTransaction(); diff --git a/test/integration/als.test.ts b/test/integration/cls.test.ts similarity index 85% rename from test/integration/als.test.ts rename to test/integration/cls.test.ts index 3dd440fd410b..702fbde15775 100644 --- a/test/integration/als.test.ts +++ b/test/integration/cls.test.ts @@ -11,7 +11,7 @@ import { sequelize, } from './support'; -describe('AsyncLocalStorage Transactions (ALS)', () => { +describe('AsyncLocalStorage (ContinuationLocalStorage) Transactions (CLS)', () => { if (!sequelize.dialect.supports.transactions) { return; } @@ -19,8 +19,8 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { disableDatabaseResetForSuite(); const vars = beforeAll2(async () => { - const alsSequelize = await prepareTransactionTest(createSequelizeInstance({ - disableAlsTransactions: false, + const clsSequelize = await prepareTransactionTest(createSequelizeInstance({ + disableClsTransactions: false, })); class User extends Model, InferCreationAttributes> { @@ -29,18 +29,18 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { User.init({ name: DataTypes.STRING, - }, { sequelize: alsSequelize }); - await alsSequelize.sync({ force: true }); + }, { sequelize: clsSequelize }); + await clsSequelize.sync({ force: true }); - return { alsSequelize, User }; + return { clsSequelize, User }; }); describe('context', () => { - it('does not use ALS on manually managed transactions', async () => { - const transaction = await vars.alsSequelize.startUnmanagedTransaction(); + it('does not use AsyncLocalStorage on manually managed transactions', async () => { + const transaction = await vars.clsSequelize.startUnmanagedTransaction(); try { - expect(vars.alsSequelize.getCurrentAlsTransaction()).to.equal(undefined); + expect(vars.clsSequelize.getCurrentClsTransaction()).to.equal(undefined); } finally { await transaction.rollback(); } @@ -50,11 +50,11 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { let t1id; let t2id; await Promise.all([ - vars.alsSequelize.transaction(async () => { - t1id = vars.alsSequelize.getCurrentAlsTransaction()!.id; + vars.clsSequelize.transaction(async () => { + t1id = vars.clsSequelize.getCurrentClsTransaction()!.id; }), - vars.alsSequelize.transaction(async () => { - t2id = vars.alsSequelize.getCurrentAlsTransaction()!.id; + vars.clsSequelize.transaction(async () => { + t2id = vars.clsSequelize.getCurrentClsTransaction()!.id; }), ]); expect(t1id).to.be.ok; @@ -63,13 +63,13 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { }); it('supports nested promise chains', async () => { - await vars.alsSequelize.transaction(async () => { - const tid = vars.alsSequelize.getCurrentAlsTransaction()!.id; + await vars.clsSequelize.transaction(async () => { + const tid = vars.clsSequelize.getCurrentClsTransaction()!.id; await vars.User.findAll(); - expect(vars.alsSequelize.getCurrentAlsTransaction()!.id).to.be.ok; - expect(vars.alsSequelize.getCurrentAlsTransaction()!.id).to.equal(tid); + expect(vars.clsSequelize.getCurrentClsTransaction()!.id).to.be.ok; + expect(vars.clsSequelize.getCurrentClsTransaction()!.id).to.equal(tid); }); }); @@ -80,10 +80,10 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { let transactionSetup = false; let transactionEnded = false; - const alsTask = vars.alsSequelize.transaction(async () => { + const clsTask = vars.clsSequelize.transaction(async () => { transactionSetup = true; await delay(500); - expect(vars.alsSequelize.getCurrentAlsTransaction()).to.be.ok; + expect(vars.clsSequelize.getCurrentClsTransaction()).to.be.ok; transactionEnded = true; }); @@ -98,16 +98,16 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { }); expect(transactionEnded).not.to.be.ok; - expect(vars.alsSequelize.getCurrentAlsTransaction()).not.to.be.ok; + expect(vars.clsSequelize.getCurrentClsTransaction()).not.to.be.ok; // Just to make sure it didn't change between our last check and the assertion expect(transactionEnded).not.to.be.ok; - await alsTask; // ensure we don't leak the promise + await clsTask; // ensure we don't leak the promise }); it('does not leak variables to the following promise chain', async () => { - await vars.alsSequelize.transaction(() => {}); - expect(vars.alsSequelize.getCurrentAlsTransaction()).not.to.be.ok; + await vars.clsSequelize.transaction(() => {}); + expect(vars.clsSequelize.getCurrentClsTransaction()).not.to.be.ok; }); it('does not leak outside findOrCreate', async () => { @@ -132,7 +132,7 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { }); it('automatically uses the transaction in all calls', async () => { - await vars.alsSequelize.transaction(async () => { + await vars.clsSequelize.transaction(async () => { await vars.User.create({ name: 'bob' }); return Promise.all([ @@ -143,7 +143,7 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { }); it('automagically uses the transaction in all calls with async/await', async () => { - await vars.alsSequelize.transaction(async () => { + await vars.clsSequelize.transaction(async () => { await vars.User.create({ name: 'bob' }); expect(await vars.User.findAll({ transaction: null })).to.have.length(0); expect(await vars.User.findAll({})).to.have.length(1); @@ -152,10 +152,10 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { }); it('promises returned by sequelize.query are correctly patched', async () => { - await vars.alsSequelize.transaction(async t => { - await vars.alsSequelize.query('select 1', { type: QueryTypes.SELECT }); + await vars.clsSequelize.transaction(async t => { + await vars.clsSequelize.query('select 1', { type: QueryTypes.SELECT }); - return expect(vars.alsSequelize.getCurrentAlsTransaction()).to.equal(t); + return expect(vars.clsSequelize.getCurrentClsTransaction()).to.equal(t); }); }); @@ -172,7 +172,7 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { function testHooks({ method, hooks: hookNames, optionPos, execute, getModel }: Params) { it(`passes the transaction to hooks {${hookNames.join(',')}} when calling ${method}`, async () => { - await vars.alsSequelize.transaction(async transaction => { + await vars.clsSequelize.transaction(async transaction => { const hooks = Object.create(null); for (const hookName of hookNames) { @@ -199,7 +199,7 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { for (const [hookName, spy] of Object.entries(hooks)) { expect( spy, - `hook ${hookName} did not receive the transaction from ALS.`, + `hook ${hookName} did not receive the transaction from AsyncLocalStorage.`, ).to.have.been.calledWith(...spyMatcher); } }); @@ -362,7 +362,7 @@ describe('AsyncLocalStorage Transactions (ALS)', () => { describe('paranoid restore', () => { const vars2 = beforeAll2(async () => { - const ParanoidUser = vars.alsSequelize.define('ParanoidUser', { + const ParanoidUser = vars.clsSequelize.define('ParanoidUser', { name: DataTypes.STRING, }, { paranoid: true }); diff --git a/test/support.ts b/test/support.ts index 8e7b8dfd7665..d0f1104fbaaf 100644 --- a/test/support.ts +++ b/test/support.ts @@ -163,8 +163,8 @@ export function createSequelizeInstance(options: Options = {}): Sequelize { pool: config.pool, dialectOptions: options.dialectOptions || config.dialectOptions || {}, minifyAliases: options.minifyAliases || config.minifyAliases, - // the test suite was written before ALS was turned on by default. - disableAlsTransactions: true, + // the test suite was written before CLS was turned on by default. + disableClsTransactions: true, }); if (process.env.DIALECT === 'postgres-native') {