Passing a new parameter to commands
Heyo!
I am converting my bots to Sapphire, and on one of them, I pass the entity manager of my ORM to each command as I call them so I don't create too many (or else it creates a memory leak). So basically, I create an entity manager every time there's an event, instead of every time I need one.
That worked fine before Sapphire, because I was the one calling my commands. But now, I am not anymore! So I thought about a way to do it.
I could extend the container and add an "em" key to it. Then, iirc, there's an event Sapphire emits before an application command is called. I could plug into that event to initialize the entity manager in the container, and destroy it after the command is done (if there's an event for that too).
Do you think that's a good approach? If not, what would you suggest?
Thank you!
66 Replies
@Helpers
Is this mikro-orm?
ye
Just add it to the container
before calling login
and you wouldn't need to pass it down to commands
all pieces have this.container
and container can also just be imported
I used to have only one em
And you still can
And when I did, queries would collide
oh
Vladdy lemme talk >:C
👀
No
:3
You can't cut me off in text chat >:C
WATCH
He can cut you off in other ways tho
I attached the db to
container.db
, and then used this decorator for every method that needed to fork the em
Example:
AYOOO
Docs on the original decorator: https://mikro-orm.io/docs/identity-map
And yeah, what Lioness said
while yall are goofing about 😒
My original suggestion would have been to extend Args but... that wouldn't work outside message commands lmao
There is a context object in the third arg tho
Aight what Lioness is suggesting is very interesting, lemme look into it
I'm still very foreign to decorators
but they look sexy
(kyra shut up)
And if this happens synchronously, you can attach events to augment said context object
cool beans
if you want to see my full mikro orm setup for ideas, the repo I'm citing is this one: https://github.com/arimajs/Arima
it may be out of date now though
Won't that fork the em every time I use the decorator though?
Yes, but I think that's what you want
It's not when I did that, it would have memory leaks
I need it to be super optimized
Why?
Idk, I just observed that :p
I'd ask in the mikro-orm slack so an expert can help, but I'm pretty sure one of the points of request context is to prevent memory leaks.
I asked them and they were like "Ye, NodeJS takes up all the memory it can that's how it is" lol
Yknow what I'll try again
shrug
Worst case scenario the valorant server doesn't have voicechats anymore :]
Does Mikro not do pooling at all? o.o
It does
I'm confused about your original question then. You want to instantiate a new entity manager on demand instead of reusing the same one to save memory?
When I was using the same one for everything queries would collide
Yeah, that's why you would fork it
Yeah, so I started forking it every time I would need one
And memory leak
Ok your approach in your repo seems much better than mine lol
I don't understand one thing though
export const UseRequestContext = OriginalUseRequestContext.bind(null, container.db.orm);like
container.db.orm
depends on how your code looks like, if you get the EM fork once and work with that, its ok, but you dont want multiple forks in one context = in one event handler, which is the same as one requestI think what he meant is that if you fork it once per command run, you'll be fine. But, if you access the getter multiple times and fork it multiple times in the same scope, you won't?
What's that
check index.ts
container.db is your databasemanager
but your databasemanager doesn't have an orm field
So you're just hot-creating the field
It does
Huh
Why not declaring it as a property?
If you put modifiers on params in the constructor, typescript automatically places it in a property of the same name
(public readonly are the modifiers)
Ooooooooooooh
Just like in PHP 8
Ok sorry for comparing TS to PHP
I will repent
ok now I understand
Thank youuuuuuuu
@kyra 🩵🩷🤍🩷🩵 >:c
I watch u
no problem
I can make you scream in DMs
what does kyra mean by that
NOTHING
@lioness100 Let's say I have multiple methods in one class that use this.container.db
Should I add the decorator to all of those methods?
Yeah
ok ty
Okay so I'm putting that everywhere it's needed, and I am now in a file where I added the decoration but the file does not have the container key because it's not extending anything from Sapphire
What's the best way to bring the container there?
You can import container from
@sapphire/framework
Ah!
ty :3
👍
I was scared I would have to create a store for my file ;-;
But, also, if you use the decorator in the message I'm replying to, you probably won't have that problem, because you can bind the orm to the decorator and never have to input it again
I don't understand, sorry
If you import the decorator from mikro-orm, you'd have to do:
And you'd have to input
container.db.orm
in every usage of the decorator for every class. However, if you create utils/decorators.ts
or similar and paste:
You can then import UseRequestContext
from that file instead, which is already bound to container.db.orm
, so you can do:
Fewer imports, less repetitionAnd then use "container" directly inside?
Sorry, I don't understand
Like
in the code of the methods
I have to use container.database
but if I don't import container, I can't, right?
oh, I misunderstood
yeah you'd still need to import it
Ok
Ok so now this is the error I have:
And before calling login:
I just removed the "solved" tag because it's not working quite yet
Ok that error is fixed, it was just because I use the decorator on getters. But now I have another error 👀 . I'll try to fix it a bit before reporting here
Aaaaand I fixed the rest myself, thank you again everyone!