Am I supposed to use entity manager provided from transactional function? #5585
samuelbednarcik
started this conversation in
General
Replies: 2 comments 1 reply
-
Can you provide a reproduction? If its something to fix (which surely might be the case), I would like to see one first. |
Beta Was this translation helpful? Give feedback.
0 replies
-
Sure, here you go: class SomeService {
constructor(private readonly em: EntityManager) {}
public async doSomething(): Promise<void> {
await this.em.transactional(async () => {
await doSomeOtherThing();
}, { ignoreNestedTransactions: true })
}
public async doSomeOtherThing(): Promise<void> {
await this.em.transactional(async () => {
})
} This will correctly handle db calls so they are part of the top level transaction, but it still uses savepoints event it is disabled in options. The reason for that is that when calling transactional function on em, it checks disableTransaction option on current instance ( this.em ) and not on "child" em. For now, we came up with this solution: import { EntityManager, TransactionContext } from '@mikro-orm/postgresql';
export function Transactional() {
return function (_target: any, _propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value;
descriptor.value = function (...args: unknown[]) {
let em = (this as { em?: EntityManager }).em;
if (!em) {
throw new Error('Transactional decorator can be only applied to method of class with em property.');
}
const trxContextEm = TransactionContext.currentTransactionContext()?.em;
return (trxContextEm ?? em).transactional(
() => {
return originalMethod!.apply(this, args);
},
{ ignoreNestedTransactions: true },
);
};
};
} |
Beta Was this translation helpful? Give feedback.
1 reply
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Handling entity managers with transactional function confuses me. The handler function argument in transactional function provides an entity manager. Am I supposed to use this entity manager in nested function calls or I can rely on transactional context?
For example: ArticleService -> BillingService -> UserService. Each call is wrapped in transaction. I was hoping i can avoid passing em argument to each function like its is when using pure knex.
We went with the second option and it seems to work pretty well ( checked by console logging entity manager id ) until we tried disabling nested transactions to avoid savepoints. Id of entity manager is always resolved from context but the options are not. So if I'm using nested transactions, it gets disableTransaction value from this (this.disableTransaction), not from the context. So it creates a savepoint even when transactions are disabled. Is it a bug or we are using it wrong?
Basically what we want to do is avoid passing em across function calls and disable savepoints.
Beta Was this translation helpful? Give feedback.
All reactions