Search code examples
typescripttransactionssequelize.js

Query in Sequelize Transaction does not update database


I'm trying to wrap our queries in transactions. The queries run fine without the transaction, however when I add the transaction it says it executes but nothing gets added to the Db.

 import { Sequelize } from 'sequelize';
 import SomeModel from '../database/models/some-model/';
 ...

 @Inject('SEQUELIZE')
 private readonly sequelizeInstance: Sequelize,

 ...

 importSomething = {
    try {
        const somethings = await this.someService.getSomething();
        if (Array.isArray(somethings)) {
            const t = await SomeModel.sequelize.transaction();
            const transactionHost = { transaction: t };
            await SomeModel.bulkCreate(somethings, {
                ignoreDuplicates: true,
                ...transactionHost
            }).then(() => logger.info('some data has been saved'));
        } else {
            const message = 'No data available.';
            logger.info(message);
            return message;
        }
    } catch (e) {
        const message = 'Error trying to import somethings.';
        return LogExceptionResponse(
            this.SERVICE_NAME,
            GetCallerMethod(),
            message,
            e
        );
    }
}

on the console I get the following:

            Executing (a7a21664-1c33-46ba-863d-376cd8d4daca): INSERT IGNORE INTO `some_log` 
              <things to insert>},
        {
          plain: false,
          raw: false,
          logging: [Function: log] { prototype: {} },
          showWarnings: false,
          validate: false,
          hooks: true,
          individualHooks: false,
          ignoreDuplicates: true,
          transaction: Transaction {
            sequelize: Sequelize {
              options: [Object],
              config: [Object],
              dialect: [MysqlDialect],
              queryInterface: [MySQLQueryInterface],
              models: [Object],
              modelManager: [ModelManager],
              connectionManager: [ConnectionManager],
              repositoryMode: false
            },
              savepoints: [],
              _afterCommitHooks: [],
              options: { type: 'DEFERRED', isolationLevel: null, readOnly: false },
              parent: undefined,
              name: undefined,
              id: 'a7a21664-1c33-46ba-863d-376cd8d4daca',
              connection: Connection {
                _events: [Object: null prototype],
                _eventsCount: 1,
                _maxListeners: undefined,
                config: [ConnectionConfig],
                  stream: [Socket],
                  _internalId: 3,
                  _commands: [Denque],
                  _command: undefined,
                  _paused: false,
                  _paused_packets: [Denque],
                  _statements: [LRUCache],
                  serverCapabilityFlags: 3489660927,
                  authorized: true,
                  sequenceId: 2,
                  compressedSequenceId: 0,
                  threadId: 227770646,
                  _handshakePacket: [Handshake],
                  _fatalError: null,
                  _protocolError: null,
                  _outOfOrderPackets: [],
                  clientEncoding: 'utf8',
                  packetParser: [PacketParser],
                  serverEncoding: 'utf8',
                  connectTimeout: null,
                  connectionId: 227770646,
                  _authPlugin: [Function (anonymous)],
                  uuid: 'a7a21664-1c33-46ba-863d-376cd8d4daca',
                  [Symbol(kCapture)]: false
                }
              },
              model: SomeModel,
              returning: true,
              fields: [ 'id', 'someId', 'reason', 'createdAt' ],
              type: 'INSERT'
            }
23-03-07 14:50:06 INFO: some data has been saved

I've also tried

await this.sequelizeInstance.transaction(async (t) => {
                const transactionHost = { transaction: t };
                ... 

but I get sequelize is not a function as an error.

and

const t = Sequelize.transaction()

throws a transaction does not exist on type of Sequelize.

the database setup looks like this

import { ConfigService } from '@nestjs/config';
import { Sequelize } from 'sequelize-typescript';
import { Dialect } from 'sequelize/types';
import models from './models/index';
import winston from 'winston';

export const databaseProviders = [
    {
        provide: 'SEQUELIZE',
        inject: [ConfigService],
        useFactory: async (configService: ConfigService) => {
            const dialect = configService.get('DATABASE_DIALECT');
            const host = configService.get('DATABASE_HOST');
            const username = configService.get('DATABASE_USER');
            const password = configService.get('DATABASE_PASSWORD');
            const database = configService.get('DATABASE');

            const sequelize = new Sequelize({
                dialect: dialect as Dialect,
                host: host,
                username: username,
                password: password,
                database: database,
                logging: winston.error,
                pool: {
                    max: 50,
                    min: 0,
                    acquire: 60000,
                    idle: 10000
                }
            });
            sequelize.addModels(models);
            await sequelize.sync();
            return sequelize;
        }
    }
];

Thanks in advance.


Solution

  • In case of creating an unmanaged transaction you need to explicitly commit/rollback it:

    const t = await SomeModel.sequelize.transaction();
    try {
     const transactionHost = { transaction: t };
     await SomeModel.bulkCreate(somethings, {
       ignoreDuplicates: true,
       ...transactionHost
     })
     await t.commit();
    catch (err) {
      await t.rollback();
    }
    

    In case of a managed transaction just check you call transaction on Sequelize instance:

    await this.sequelizeInstance.transaction(async (transaction) => {
     await SomeModel.bulkCreate(somethings, {
       ignoreDuplicates: true,
       {
         transaction
       }
     })
    });