neon-bindings / neon

Rust bindings for writing safe and fast native Node.js modules.
https://www.neon-bindings.com/
Apache License 2.0
8k stars 283 forks source link

Bindings blocking node runtime? #993

Closed Will-Smith11 closed 1 year ago

Will-Smith11 commented 1 year ago

Currently am trying to have async update hooks with neon bindings. Im currently doing this by storing state in rust and them from typescript calling a poll function. However when i try to make these poll functions async ( ie loop the poll calls in an async fn ). So i can do other calculations, it seems to block the runtime and no other progression occurs. Im wondering what the workaround for this would be?

kjvalencik commented 1 year ago

Do you mean the JavaScript runtime or the tokio runtime? The JavaScript runtime is single threaded and any time JavaScript is being executed (i.e., when you have access to a Context) it is blocked.

Will-Smith11 commented 1 year ago

Yes i mean javascript. That makes sense, however in regular javascript you can call an async function that loops and the javascript scheduler will move between different pending promises (ie like the loop call future will be moved off main thread to complete other tasks before being moved back on). However that doesnt seem to be the case when im doing calls to neon

Will-Smith11 commented 1 year ago

And example of this would be

Const a = asyncfncall();
Console.log("called async fn");
... other code
Await a;

With regular javascript this works fine. However with neon it doesn't

flisky commented 1 year ago

just for sure, does the following work for you? @Will-Smith11

console.log("called async fn");
// ... other code
await asyncfncall();

Do you do any blocking in asyncfncall? Could you please give a repo to reproduce this?

Will-Smith11 commented 1 year ago

just for sure, does the following work for you? @Will-Smith11

console.log("called async fn");
// ... other code
await asyncfncall();

Do you do any blocking in asyncfncall? Could you please give a repo to reproduce this?

I was able to resolve this. sorry im a bit of a ts/js noob compared to rust. I was able to fix this by just injecting a promise timeout into my async fn call to encourage the runtime to park the task.

kjvalencik commented 1 year ago

Glad you figured it out! Resolving a promise usually isn't enough to yield to the event loop because it's a microtask and those get pushed to the front of the queue.

setTimeout, setImmediate, etc, will yield because those push to the back.