Consider a NestJS service method that wraps multiple database operations inside a transaction using TypeORM's queryRunner. If one operation fails and throws an error, what is the expected behavior of the transaction?
async function performOperations(queryRunner) { await queryRunner.startTransaction(); try { await queryRunner.manager.save(entity1); await queryRunner.manager.save(entity2); throw new Error('Failure'); await queryRunner.commitTransaction(); } catch (error) { await queryRunner.rollbackTransaction(); throw error; } finally { await queryRunner.release(); } }
Think about what a transaction does when an error occurs inside it.
When an error occurs inside a transaction, the rollbackTransaction() method undoes all changes made during the transaction. This means none of the entities are saved.
Choose the code snippet that correctly starts a transaction, performs an operation, and commits it using QueryRunner.
Check the exact method names on QueryRunner for starting and committing transactions.
The correct methods are startTransaction() to begin and commitTransaction() to commit. All are async and should be awaited.
Review the following code snippet. It throws a 'QueryRunner already released' error when running multiple transactions sequentially. What is the cause?
async function runTransaction(data) { const queryRunner = dataSource.createQueryRunner(); await queryRunner.connect(); await queryRunner.startTransaction(); try { await queryRunner.manager.save(data); await queryRunner.commitTransaction(); } catch (err) { await queryRunner.rollbackTransaction(); } finally { await queryRunner.release(); } } await runTransaction(entity1); await runTransaction(entity2);
Consider what happens to the queryRunner after release() is called.
Each call creates a new queryRunner and releases it properly. The error occurs if the same queryRunner instance is reused after release. Here, the code is correct if each call uses a fresh queryRunner. The error usually means queryRunner is reused after release.
Given the following pseudo-code using TypeORM's QueryRunner with savepoints, what data remains saved after execution?
await queryRunner.startTransaction(); try { await queryRunner.manager.save(entityA); await queryRunner.query('SAVEPOINT sp1'); await queryRunner.manager.save(entityB); throw new Error('Error after sp1'); await queryRunner.query('RELEASE SAVEPOINT sp1'); await queryRunner.commitTransaction(); } catch (e) { await queryRunner.query('ROLLBACK TO SAVEPOINT sp1'); await queryRunner.commitTransaction(); }
Think about what rolling back to a savepoint does inside a transaction.
Rolling back to a savepoint undoes changes after that savepoint but keeps earlier changes. So entityA is saved, entityB is rolled back.
In NestJS applications using database transactions, why is it important to keep transactions short and avoid long-running ones?
Consider how databases handle locks during transactions.
Long-running transactions hold locks longer, blocking other operations and hurting performance and scalability.