-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
a better solution for unit of work implementation. #1
Comments
@khalvai Hi, thanks for the feedback ) For example, imagine that we have such a code
Since you have a global transaction per request, they will compete and bugs are possible. |
@khalvai |
Hi, thanks for you response. You know in this senario: await this.unitOfWork.transaction(...)
await this.unitOfWork.transaction(...) we won't have any problem, because after each transaction we will clear the context: async transaction<T>(fn: () => Promise<T>): Promise<T> {
return await this.prisma.$transaction(async (tx) => {
RequestContextService.setTransactionConnection(tx);
const t = await fn();
RequestContextService.cleanTransactionConnection();
return t;
});
} I have not tried AsyncLocalStorage, but i guess we must instatiate an object of that class for each unti of work... |
@khalvai when you have transactions running in parallel within the same query, then the context will be cleared uncontrollably and there may be bugs
If you make async local storage, it will remember the transaction not for the request, but for the local call. in other words, parallelism within a single request will be possible. if all requests work in a row with await, then your scheme will work fine and it's good. |
yeah, if it creates a local sotrage for each call( transaction call) then we won't have problem with async calls.. |
@khalvai |
@zhuravlevma
async save(report: ReportEntity): Promise<ReportEntity> {
const reportOrm = ReportMapper.mapToOrm(report);
const savedReport = await this.typeormClient.client
.getRepository(ReportOrmEntity)
.save(reportOrm);
return ReportMapper.mapToDomain(savedReport);
} i think you are using it: return this.uow.transaction(async () => {
const updatedWh = await this.saveWhPort.saveWarehouse(warehouse);
await this.saveReport.save(report);
return updatedWh;
}); |
@khalvai each transaction call will save its own transaction |
@zhuravlevma i meant, how exactly this code, using transaction connect? async saveWarehouse(warehouse: WarehouseEntity): Promise<WarehouseEntity> {
const warehouseORM = WarehouseMapper.mapToORM(warehouse);
const whOrm = await this.typeormClient.client
.getRepository(WarehouseOrmEntity)
.save(warehouseORM);
return WarehouseMapper.mapToDomain(whOrm);
} we aimed to run this method within a transaction with other method. |
Hi there
Really appreciate what you have done, i think there are some bad practices in code and it can be improved for i.e:
here
This abstraction might not be ideal because it relies on TypeOrm properties. If we decide to switch to a different ORM, we would need to modify the abstraction accordingly.
I have solved this problem with abstraction and independent from ORMs:
https://github.com/khalvai/unti-of-work/blob/main/src/common/prisma.unit-of-work.ts
and it is usage:
in :
https://github.com/khalvai/unti-of-work/blob/main/src/app.service.ts
The text was updated successfully, but these errors were encountered: