транзакция не полностью откатывается

#node.js #nestjs #typeorm

#node.js #nestjs #typeorm

Вопрос:

Моя проблема в том, что я выполняю транзакцию, которая включает несколько запросов, и если один из этих запросов завершается неудачно, те, которые указаны выше, не откатываются, но должны. Транзакция имеет следующую структуру (рекомендуется в официальной документации nestjs):

     public async create(createUserDto: RegisterUserDto): Promise<UserEntity> {
        const queryRunner = this.connection.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();
        try {
            const firstReqResult = await this.firstMethod(queryRunner, createUserDto);
            const secondReqResult = await this.secondMethod(firstReqResult, queryRunner);
            await queryRunner.commitTransaction();
            return secondReqResu<
        } catch (err) {
            await queryRunner.rollbackTransaction();
            throw new HttpException(err.message, HttpStatus.BAD_REQUEST);
        } finally {
            await queryRunner.release();
        }
    }
  

Итак, если первый метод записывает некоторые данные в некоторые таблицы данных и secondMethod по какой-то причине выдает ошибку, то эти данные не удаляются при откате и, следовательно, в БД появляются потерянные записи.

Одна важная вещь: эти два метода firstMethod и secondMethod сами не являются транзакциями, это просто обычные методы, которые используют queryRunner переданный им параметр.

Как правильно выполнить typeorm откат такой транзакции?

Редактировать:

Похоже, что моя попытка не сработала. Поэтому я опубликую более подробную информацию:

Вот основной метод:

     public async create(createUserDto: RegisterUserDto): Promise<UserEntity> {
        const queryRunner = this.connection.createQueryRunner();
        await queryRunner.connect();
        await queryRunner.startTransaction();
        try {
            // some code
            const profilePrivacyPermissions = await this.profilePrivacyPermissionsService.generateInitSettings(queryRunner);
            const registeredUser = await this.registerUser(user);
            await queryRunner.commitTransaction();
            return registeredUser;
        } catch (err) {
            await queryRunner.rollbackTransaction();
            throw new HttpException(err.message, HttpStatus.BAD_REQUEST);
        } finally {
            await queryRunner.release();
        }
    }
  

registerUser Метод выдает исключение.

Метод generateInitSettings выглядит следующим образом:

     public async generateInitSettings(qr: QueryRunner): Promise<ProfilePrivacyEntity[]> {
        const generatedSettings = [];
        const screenTypeIds = Object.values(EScreenType).filter(value => typeof value === 'number') as number[];
        for (const stId of screenTypeIds) {
            const setting = this.createAndSaveInitSetting(stId, qr);
            generatedSettings.push(setting);
        }
        return await Promise.all(generatedSettings);
    }
  

и createAndSaveInitSetting :

     private async createAndSaveInitSetting(screenType: number, qr: QueryRunner): Promise<ProfilePrivacyEntity> {
        const permission = new ProfilePrivacyEntity();
        permission.setScreenType(screenType)
                  .setIsEverybody(true)
                  .setIsContacts(false)
                  .setIsNobody(false);
        const createdPermission = qr.manager.getRepository(ProfilePrivacyEntity).create(permission);
        return await createdPermission.save();
    }
  

Поэтому, когда registerUser метод выдает исключение, изменения, внесенные DB generateInitSettings , не откатываются.

Комментарии:

1. Какую базу данных вы используете? Можете ли вы предоставить реализацию (точнее, вызовы queryRunner ) в this.firstMethod and this.secondMethod ?

2. Я использую PostreSQL, что касается реализации, я постараюсь что-нибудь придумать, и когда я это сделаю, я опубликую это здесь, потому что оригинальные методы довольно сложны. У меня была такая же проблема с другими, более простыми методами.

3. Добавьте некоторый код, который воспроизводит проблему.

4. @jeeves хм, кажется, мне удалось исправить эту проблему, проблема заключалась в том, что один из методов не получил контекст транзакции queryRunner. Похоже, сейчас это работает, но в любом случае я не буду удалять этот вопрос, пока не буду уверен, что исправил ошибку, если нет, я попытаюсь опубликовать минимум кода, достаточного для воспроизведения проблемы.

5. Мне придется попытаться повторить это.