Giter Site home page Giter Site logo

Comments (18)

B4nan avatar B4nan commented on September 2, 2024

You work with the global instances, that is the whole point of RequestContext helper. Internally the fork is used, you can access it via em.getContext().

from nestjs.

TLmaK0 avatar TLmaK0 commented on September 2, 2024

@B4nan Do you have any idea why in every request my folders collection increase by one? I'm not calling flush, so it doesn't persist to db.
This is my controller:

import {Controller, Post} from "@nestjs/common";   
import {Folder, Bucket} from "../domain";                    
import {InjectRepository} from '@mikro-orm/nestjs';
import {EntityRepository} from '@mikro-orm/core';                                   
                                                                                     
@Controller()                                                                       
export class FolderController {   
  constructor(                    
    @InjectRepository(Bucket) private readonly bucketsRepo: EntityRepository<Bucket>,   
  ) {}                                                                                  
         
  @Post('folders')   
  async createFolder(   
  ) {                   
    const folder = new Folder({name: 'test'});   
    const bucket = await this.bucketsRepo.findOne({companyId: '1'}, ['folders']);   
                                                                                    
    bucket.folders.add(folder);   
    this.bucketsRepo.persist(bucket);   
    console.log(bucket.folders);        
    //await this.bucketsRepo.flush();   
  }                                     
}     

Thanks for your help

from nestjs.

B4nan avatar B4nan commented on September 2, 2024

idk, enable debug mode, if you see insert queries, you are flushing somewhere. might be really misconfigured request context.

also note that there is reason to persist managed entities, flush will always go thru all managed entities. another note - flush is an action of UoW, both persist and flush on repository is just a shortcut, you always work with the EM (and its UoW instance), repository is just a thin layer on top of it (more of an extension point).

you could add console.logs to the ORM code to flush method to see from where it is called (just log new Error().stack)

from nestjs.

TLmaK0 avatar TLmaK0 commented on September 2, 2024

Thanks @B4nan. There aren't any "insert" in the logs (the table is empty). I will try to create a project to reproduce it.

from nestjs.

B4nan avatar B4nan commented on September 2, 2024

Well, if you dont see any insert queries in logs, then its not the ORM who does it. Or maybe I misunderstood what you mean by "in every request my folders collection increase by one".

from nestjs.

TLmaK0 avatar TLmaK0 commented on September 2, 2024

I mean, when I call console.log(bucket.folders) inside the controller, it prints one more folder in every request, but there isn't any folder in the table.

[query] select "e0".* from "bucket" as "e0" where "e0"."id" = '1' limit 1 [took 3 ms]
[query] select "e0".* from "folder" as "e0" where "e0"."bucket_id" in ('1') order by "e0"."bucket_id" asc [took 3 ms]
Collection {
  '0': Folder {
    name: 'test',
    bucket: Bucket { id: '1', name: 'asdfasdf', folders: [Collection] }
  },
  initialized: true,
  dirty: true
}
Collection {
  '0': Folder {
    name: 'test',
    bucket: Bucket { id: '1', name: 'asdfasdf', folders: [Collection] }
  },
  '1': Folder {
    name: 'test',
    bucket: Bucket { id: '1', name: 'asdfasdf', folders: [Collection] }
  },
  initialized: true,
  dirty: true
}
Collection {
  '0': Folder {
    name: 'test',
    bucket: Bucket { id: '1', name: 'asdfasdf', folders: [Collection] }
  },
  '1': Folder {
    name: 'test',
    bucket: Bucket { id: '1', name: 'asdfasdf', folders: [Collection] }
  },
  '2': Folder {
    name: 'test',
    bucket: Bucket { id: '1', name: 'asdfasdf', folders: [Collection] }
  },
  initialized: true,
  dirty: true
}

from nestjs.

B4nan avatar B4nan commented on September 2, 2024

That really looks like misconfigured request context. As I already said in the very first reply, you can verify it via em.getContext().id, so ensure you have different ids for each request.

Are you testing this via regular requests or is it some unit/integration test? Does it work the same if you work with EM instead of repositories?

I can assure you there is no problem with the request context class itself, if the issue is with that, it points to misconfiguration. If there was a bug in such a fundamental part, there would be many many more issues like that :] Its code is very trivial, there is not much that could be broken.

from nestjs.

B4nan avatar B4nan commented on September 2, 2024

Wild guess, but common source of weird issues is having misaligned package versions. All ORM packages need to be on the very same version, only exceptions are the nest package and highlighters.

from nestjs.

TLmaK0 avatar TLmaK0 commented on September 2, 2024

Many thanks @B4nan, I will try to review package versions. This is what I get from em.getContext().id:

import {Controller, Post} from "@nestjs/common";
import {Folder, Bucket} from "../domain";
import {InjectRepository} from '@mikro-orm/nestjs';
import {EntityRepository} from '@mikro-orm/core';

@Controller()
export class FolderController {
  constructor(
    @InjectRepository(Bucket) private readonly bucketsRepo: EntityRepository<Bucket>,
  ) {}

  @Post('folders')
  async createFolder(
  ) { 
    const folder = new Folder();
    folder.name = 'test';
    const bucket = await this.bucketsRepo.findOne('1', ['folders']);

    bucket.folders.add(folder);
    this.bucketsRepo.persist(bucket);
    console.log(this.bucketsRepo['_em'].getContext().id);
    //await this.bucketsRepo.flush();
  }
}

multiple requests returns

[query] select "e0".* from "bucket" as "e0" where "e0"."id" = '1' limit 1 [took 3 ms]
[query] select "e0".* from "folder" as "e0" where "e0"."bucket_id" in ('1') order by "e0"."bucket_id" asc [took 2 ms]
1
1
1
1
1
1

from nestjs.

B4nan avatar B4nan commented on September 2, 2024

Yeah thats definitely wrong. Try to compare what you are doing differently from the example project, as there the request context is setup properly. Or create full repro, so I can take a look.

from nestjs.

TLmaK0 avatar TLmaK0 commented on September 2, 2024

Thanks @B4nan. Finally I found the problem. I use FastifyAdapter, removing it from the app it works as expected, so there is something wrong with @mikro-orm/nestjs and Fastify. Here is a repo to test it https://github.com/proptex/nestjs-fastify-mikro-orm. If you comment the line 30 from FolderController.ts, you will get the same result without inserts in the database. Removing FastifyAdapter from line 13 in main.ts will work as expected. If it is a bug, I can help to try to fix it, but I need help to start.

from nestjs.

B4nan avatar B4nan commented on September 2, 2024

Check this PR, the detection is probably not working or they made some BC again

#4

from nestjs.

TLmaK0 avatar TLmaK0 commented on September 2, 2024

@B4nan the createDomain() from RequestContext is called in every request, but the problem is that in RequestContext.currentRequestContext() https://github.com/mikro-orm/mikro-orm/blob/v4.5.7/packages/core/src/utils/RequestContext.ts#L48, domain.active is undefined when use FastifyAdapter. Any thoughts?

from nestjs.

B4nan avatar B4nan commented on September 2, 2024

I already told you where to look, this is not about RequestContext class, this is about the middleware that is using it. See the PR #4 and check the fastify detection that is added there.

from nestjs.

TLmaK0 avatar TLmaK0 commented on September 2, 2024

I have checked and usingFastify(consumer) returns true, also forRoutesPath returns '(.*)' which is correct.

from nestjs.

TLmaK0 avatar TLmaK0 commented on September 2, 2024

This is the explanation of the behavior I found in the repro: https://github.com/proptex/nestjs-fastify-mikro-orm.

With FastifyAdapter, Fastify tries to parse the content:

https://github.com/fastify/fastify/blob/8371ba04d6ee8fb320ae1535233b3a999882fe3c/lib/contentTypeParser.js#L203 here domain.active is correct.

https://github.com/fastify/fastify/blob/8371ba04d6ee8fb320ae1535233b3a999882fe3c/lib/contentTypeParser.js#L221 now domain.active is undefined.

If domain.active is undefined, RequestContext.getEntityManager() returns undefined, then Configuration<D extends IDatabaseDriver = IDatabaseDriver>.context returns undefined too.

In EntityManager when try to getContext https://github.com/mikro-orm/mikro-orm/blob/3dd9f7717667675065d9affa12e02d87fa7a25a2/packages/core/src/EntityManager.ts#L824 there is:

em = this.useContext ? (this.config.get('context')(this.name) || this) : this;

which will use the current EntityManager instead of reuse the last created in RequestContext.

from nestjs.

TLmaK0 avatar TLmaK0 commented on September 2, 2024

@B4nan I think we should reopen the issue. I have tested it with other node versions and I can reproduce the same problem with the repro. I was not able to make it work with Fastify (no problems with express). I think the issue is the use of "domain" that is being deprecated. It could be that some one has a workaround.

from nestjs.

B4nan avatar B4nan commented on September 2, 2024

I did try to use the fastify adapter with the realworld example, and it works just fine for me, no issues with request contexts. The only endpoint that was not working was the one for favoriting articles, which is probably caused by some difference in routing (as the endpoint is not reachable from tests and returns 400, rest of them work just fine).

from nestjs.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.