'NestJS + MikroORM EntityManager Validation Error

I started migrating a project from typeorm to MikroORM and I've been facing an issue when calling the same ( or different ) repository more than once. The error is as follows:

ValidationError: Using global EntityManager instance methods for context specific actions is disallowed. If you need to work with the global instance's identity map, use 'allowGlobalContext' configuration option or 'fork()' instead.

A more detailed explanation is:

  • I am using NestJS
  • DB is postgreSQL
  • GRPC communication for this specific service ( not sure if that matters )
  • Wrapping repository calls in rxjs observables: e.g. from(this.userRepository.findOne({id: user.id})

Now, I've read through the documentation and other issues here and on github mainly regarding the EntityManager and the RequestContext. I've added the @UseRequestContext() annotation on my controller ( and injected the private readonly orm: MikroORM, instance in the constructor ):

 @GrpcMethod('UsersService', 'Login')
  @UseRequestContext()
  login(user: UserLogin): Observable<UserResponse> {
    return this.userService.login(user);
  }

The service itself calls userRepository.find... and via debug I can see the executed query and the result is fetched, however I have another call to the roleRepository later on down the line. This call fails with the error above. I've played around with it and it seems like even if I try to call the same userRepoistory.find... for a second time it will fail again: e.g.:

loginUser(user: UserLogin) {
    return this.getUserById(user.id).pipe(
      switchMap(() => this.getUserById(user.id)),
    );
  }

If I do the following inside the getUserById method however, it works like a charm:

getUserById(id: string): Observable < User > {
    const emFork = this.em.fork();
    return from(emFork.findOne(User, {
      userId: id
    }));

Basically what I am trying to understand is:

  • It says in the documentation that the function marked with @UseRequestContext() should not return anything, however when placing it on the Grpc method it works ( at least for the first repository call ). If I remove it I get the same error before calling any repositories. Am I using it correctly?
  • If the forking of the EntityManager is the correct approach, wouldn't that make creating Repository classes and injecting them obsolete? Also isn't forking it each time going create a lot of instances?
  • It's obvious I am lacking understanding on how this context works, so an explanation would be greatly appreciated!
  • Also, any other hints/tips are welcome!

Thank you for your time :)



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source