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
Inintended caching of EntityManager by EntityRepository from within a transactional context #5395
Comments
It is worth noting that the aforementioned af87693 explicitly states "do not use context in em.getRepository()", however it is still used there (v6.1.12) and was added by b5b03a6#diff-a62cd78c400d99253a3c0fb5a9bf26e1e63e0deb511059d28ba51014b58242ddR146 but the change does not seem related to the commit's intention. |
Could this be causing other unintended consequences? I’m currently trying to track down an issue(so I can make a reproduction) where entities are deleted and recreated with the same ID. I thought it was an issue our side (and might be), but it’s seemingly random, like the identity map is incorrect on some occasions. |
@ashleyww93 You can override // replace `PostgreSqlDriver` with you respective driver
export class ExtendedEntityManager extends EntityManager<PostgreSqlDriver> {
public getRepository<Entity extends object>(entityName: EntityName<Entity>) {
const repository = super.getRepository(entityName);
const currentContext = this.id;
const repoContext = repository.getEntityManager().id;
if (currentContext !== repoContext) {
throw new Error(
`EntityRepository<${repository.getEntityName()}> context (${repoContext}) did not match the current EntityManager context (${currentContext})!`,
);
}
return repository as any;
}
} defineConfig({
// ...
entityManager: ExtendedEntityManager,
}); Docs: https://mikro-orm.io/docs/entity-manager#extending-entitymanager |
@ashleyww93 If this issue is the culprit of your problem, it may appear random because it requires the first |
Yeah correct, and reverting this bit is not making any of the existing tests fail, I guess I will go with that, worst case we will revert it, but I agree it looks unrelated to the commit. That change also makes the e2e test suite of the real-world app pass, so it feels safe. |
@B4nan Awesome! Thanks. Any chance the test suite can be amended with a case like this? await em.transactional(async _ => {
// first even call to a repository, em is not tx-specific
await em.getRepository(Post).find({id: 1});
});
assert.equal(em.id, em.getRepository(Post).getEntityManager().id) |
Yeah, for sure, I will include the repro from OP. |
Describe the bug
According to the docs (https://mikro-orm.io/docs/identity-map#how-does-requestcontext-helper-work) it should be pefectly safe to use a more "global" EM instance from within a transactional or request context (i.e. not having to pass down the EM instance passed to the transaction callback).
However, this expectation breaks in at least one specific scenario that is very easy to replicate.
When the first time a repository is accessed is within a transaction but from the "outside" EM instance (the one on which
.transactional
was called) then the repository will get "stuck" with the transaction-specific EM instance (can be verified by comapringem.id
) which in the best case leads toDriverException: Transaction query already complete
and in the worst case can cause data corruption due to improper isolation.This problem can occur naturally when using MikroORM with NestJS and having services that call one another while each relies primarily on the (global) injected EM instance.
It is worth noting that
.getContext()
on the "stuck" EM instance is a no-op and returns self, thus the repository is corrupted for the entire lifetime of the application process.Reproduction
Reproduction:
If the repository happened to be accessed prior to a transaction, the issue does not happen:
Using tx-specific instance or explicitly calling
.getContext()
inside the transaction also resolves the issue:What driver are you using?
@mikro-orm/postgresql
MikroORM version
6.1.12
Node.js version
18.16.0
Operating system
MacOS
Validations
The text was updated successfully, but these errors were encountered: