-
-
Notifications
You must be signed in to change notification settings - Fork 544
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
Support for multiple Mikro-ORM instances with context (RequestContext / AsyncLocalStorage) #872
Comments
What about this:
ok, I should have checked your commit sooner, I see you basically did exactly that :] that sounds like correct way to me Something like this could work for the context helper: import domain, { Domain } from 'domain';
import { EntityManager } from '../EntityManager';
import { Dictionary } from '../typings';
export type MultiORMDomain = Domain & { __mikro_orm_context?: MultiRequestContext };
/**
* For node 14 and above it is suggested to use `AsyncLocalStorage` instead,
* @see https://mikro-orm.io/docs/async-local-storage/
*/
export class MultiRequestContext {
private static counter = 1;
readonly id = MultiRequestContext.counter++;
constructor(readonly map: Map<string, EntityManager>) { }
/**
* Creates new RequestContext instance and runs the code inside its domain.
*/
static create(map: Map<string, EntityManager>, next: (...args: any[]) => void): void {
const forks = new Map<string, EntityManager>();
map.forEach((em, name) => forks.set(name, em.fork(true, true)));
const context = new MultiRequestContext(forks);
const d = domain.create() as MultiORMDomain;
d.__mikro_orm_context = context;
d.run(next);
}
/**
* Creates new RequestContext instance and runs the code inside its domain.
* Async variant, when the `next` handler needs to be awaited (like in Koa).
*/
static async createAsync(map: Map<string, EntityManager>, next: (...args: any[]) => Promise<void>): Promise<void> {
const forks = new Map<string, EntityManager>();
map.forEach((em, name) => forks.set(name, em.fork(true, true)));
const context = new MultiRequestContext(forks);
const d = domain.create() as MultiORMDomain;
d.__mikro_orm_context = context;
await new Promise((resolve, reject) => {
d.run(() => next().then(resolve).catch(reject));
});
}
/**
* Returns current RequestContext (if available).
*/
static currentRequestContext(): MultiRequestContext | undefined {
const active = (domain as Dictionary).active as MultiORMDomain;
return active ? active.__mikro_orm_context : undefined;
}
/**
* Returns current EntityManager (if available).
*/
static getEntityManager(name: string): EntityManager | undefined {
const context = MultiRequestContext.currentRequestContext();
return context ? context.map.get(name) : undefined;
}
} |
Any updates on this? I am planning to ship 4.1 soon, will be happy to include |
Not yet, I have other priorities this week. It may take a while.
|
Does mikro supports multiple instances without RequestContext? I saw that If I use |
|
Sounds good! what about global static |
Thats only for decorators, so with Also as long as you compile your TS via tsc, the decorators will use current path to entity in the global storage key, so its possible to have multiple entities with same name in different files (as long as you do not try to use them both in one ORM instance) even with decorators. |
v4.3 will allow specifying Let me know if it works, will be happy to reopen. |
Wow, thanks. I was just about to pick this up again and just noticed you closed it. I'll add a test ticket to my workload to test this soon. |
Is your feature request related to a problem? Please describe.
I need to use Mikro-ORM to connect to different database instances, so I have multiple Mikro ORM instances running in my NestJS application. (One is located within an npm dependency, the other is located in the NestJS application directly).
At the moment it seems I cannot use the Mikro-ORM instance in the npm dependency, because the RequestContext helper only supports a single Mikro-ORM entity manager -- more specifically, whatever Mikro ORM EM is used in the
RequestContext.create
call.Describe the solution you'd like
I'd like to find a solution that allows multiple instances of entity manager, belonging to different mikro orm instances, to coexist, without them interfering with one another.
A potential way to do this is to combine the following solutions:
Describe alternatives you've considered
I've considered rolling the two database instances into one, but that will likely cause trouble for us down the road since we need to be able to scale them independently.
Additional context
I have a commit that makes EntityManager 'name-aware' over at hilkeheremans@3c84e9a. Note: I could not verify this via tests or add new tests, since I can't get the tests to run properly. Unclear what I need to do to fully set up the schema in the db's of the docker containers.
I believe making RequestContext/AsyncLocalStorage compatible with multiple Entity Managers may require a slightly more fundamental change. The way this context is created now, eg via
RequestContext.create()
forces you to specify the entity manager you want to fork. Is this still the road we want to take, or is an alternative method, ie letting the user ofRequestContext
specify a set ofroot entity managers
initially in code, all of which can then beforked
on each new request? This would also simplify the API.Either way, these new versions of RequestContext/AsyncLocalStorage would be breaking changes, so it would probably make sense to create these new versions alongside the existing ones, so users can opt-in to them at will.
Thanks a bunch for your input and let me know what I am missing.
The text was updated successfully, but these errors were encountered: