Aliheym / typeorm-transactional

A Transactional Method Decorator for TypeORM that uses Async Local Storage or cls-hooked to handle and propagate transactions between different repositories and service methods.
MIT License
201 stars 27 forks source link

[Feature Request] Transactional support on DataSource and EntityManager #2

Closed Migushthe2nd closed 2 years ago

Migushthe2nd commented 2 years ago

I do not inject entity repositories everywhere, therefore I sometimes use dataSource.manager. Queries made via the data source unfortunately don't seem to be executed inside the transaction. Without support for other (basic) usecases of typeorm, the module is rather difficult to use.

Reproduction

@Transactional()
function example() {
        const istransaction1 = await this.entityRepository.createQueryBuilder()
            .select("txid_current_if_assigned() is not null AS is_transaction")
            .getRawOne();
        console.log(istransaction1) // true

        const istransaction2 = await this.entityRepository.query("select txid_current_if_assigned() is not null AS is_transaction");
        console.log(istransaction2) // false

        const istransaction3 = await this.entityRepository.manager.createQueryBuilder(Entity, "e")
            .select("txid_current_if_assigned() is not null AS is_transaction")
            .getRawOne();
        console.log(istransaction3) // false

        const istransaction4 = await this.dataSource.manager.createQueryBuilder(Entity, "e")
            .select("txid_current_if_assigned() is not null AS is_transaction")
            .getRawOne();
        console.log(istransaction4) // false

        const istransaction5 = await this.dataSource.createQueryBuilder(Entity, "e")
            .select("txid_current_if_assigned() is not null AS is_transaction")
            .getRawOne();
        console.log(istransaction5) // false
}

Expected behaviour

All of these queries should be executed in the same transaction, not just the query made on the entity repository.

Environment

Typeorm 0.3.7, NestJS

Aliheym commented 2 years ago

Hi, thanks for the issue. The original library "patched" only the repositories and I decided not to deviate from that. But since I don't have any plans to support old library and considering new versions of TypeORM it makes sense to add library functionality on DataSource level too.

Migushthe2nd commented 2 years ago

I have taken a look at this module, and to me it seems that in order for Transactional to support more functionality of TypeOrm, the EntityManager system should be replaced with a QueryRunner management system.

For example, if you want to support Repository.query() which calls -> EntityManager.query() -> DataSource.query() -> QueryRunner.query(), a custom QueryRunner which is in a transaction must be used here. Currently, this module calls DataSource.transaction(), which calls EntityManager.transaction(), which only has access to the QueryRunner.manager, while we need the full query runner for the query() support.

I unfortunately don't have enough knowledge of TypeOrm's inner working, nor this module (yet) to implement support for this.