I am using NestJS with TypeORM. I have several modules and each module contain service. There are some modules that import other modules and use their services.
// In Person Module
@Injectable()
class UserService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>
) {}
public async deleteUsersByCompany(companyId: string) {
const usersToDelete = await this.usersRepository
.createQueryBuilder('user')
.where('user.companyId = :companyId', { companyId })
.getMany();
if (usersToDelete.length > 0) {
await this.usersRepository.delete(
usersToDelete.map((user) => user.id),
);
}
}
...
}
// Company Module
@Injectable()
class CompanyService {
constructor(
@InjectRepository(Company)
private companysRepository: Repository<Company>,
private usersService: UserService
) {}
public async deleteCompany(companyId: string) {
const companyToDelete = await this.companysRepository.find(companyId);
if (companyToDelete) {
await usersService.deleteUsersByCompany(companyToDelete.id)
await this.companysRepository.delete(companyToDelete);
}
}
...
}
In this example:
- I want
usersService.deleteUsersByCompanyto be atomic operation - I want
companyService.deleteCompanyto be atomic operation - Both
usersService.deleteUsersByCompanyandcompanyService.deleteCompanycan be triggered by the user
I want to wrap both actions in transaction. I've read NestJS documentation and TypeOrm documentation but couldn't find an answer how to do this properly.
The main thing here is that usersService.deleteUsersByCompany is being called by companyService.deleteCompany.
- How can I support such "nested transactions"?
- Does QueryRunner replace the Repository pattern?
- Should my services hold both Repository and Connection instances? Repository for non-transactional operations and connection to get QueryRunner?