Skip to content
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

[feature request] expose Node event loop to Java code #321

Open
larsrh opened this issue Aug 3, 2020 · 5 comments
Open

[feature request] expose Node event loop to Java code #321

larsrh opened this issue Aug 3, 2020 · 5 comments

Comments

@larsrh
Copy link

larsrh commented Aug 3, 2020

I'm running some JS code through the Node binary that's shipped with Graal. This code calls to some async Java code. I use a similar trick like in the GraalJS tests to convert a Java CompletionStage to a JS Promise:

https://github.com/graalvm/graaljs/blob/278b71516f85fec61a5ca35353ab31dc637f31db/graal-js/src/com.oracle.truffle.js.test/src/com/oracle/truffle/js/test/interop/AsyncInteropTest.java#L211

Unfortunately, if the CompletionStage is completed on another thread, this fails because of concurrent access to JS objects.

The JSAgent class contains the top-level callback-loop for Node:

https://github.com/graalvm/graaljs/blob/vm-20.1.0/graal-js/src/com.oracle.truffle.js/src/com/oracle/truffle/js/runtime/JSAgent.java

It would be gread if Java user code could dispatch callbacks on that loop. This would solve the concurrent access problem: I could register a handler on the CompletionStage that, instead of resolving the Promise directly (on the wrong thread), would schedule the resolution on the main Node thread.

@eleinadani
Copy link
Contributor

Hi @larsrh, JSAgent is an internal implementation class, and we cannot expose it to user applications. In our concurrency model, the user application needs to ensure that no concurrent access on objects belonging to the same Context can happen. In this article we have a few examples showing how multiple threads can use promises concurrently

@larsrh
Copy link
Author

larsrh commented Aug 10, 2020

Of course; I'm not arguing that JSAgent should be exposed just like that.

The article you linked isn't applicable in my scenario. The application is started through node, which means that the Context (and execution thread) is fully in control of the Node REPL. It is impossible to run any other code on that thread. Of course I could use synchronized or other things if I were to create a Context (or a pool) myself, but I don't.

@larsrh
Copy link
Author

larsrh commented Aug 10, 2020

Addendum: You can imagine my feature request like a setImmediate equivalent that I can call from Java.

@mikehearn
Copy link
Contributor

You can do that. Check out https://mikehearn.github.io/nodejvm/ or the articles in the GraalVM Medium blog. The linked program inverts NodeJS support so the JVM runs first, but it shows how to relay Java calls into the NodeJS thread with some transparency. The trick is to create a worker in the NodeJS world and then attach it to a Java LinkedBlockingQueue onto which you push closures. You can then schedule any Java closure to be executed in the NodeJS thread. It would of course be nice if the NodeJS GraalVM integration was more direct, but it is not too difficult to do this.

@jpg0
Copy link

jpg0 commented Apr 8, 2021

I'm not sure if this comment exactly reflects the desire of this issue (I'm happy to open a new one), however I think that it's important to disambiguate between: support for setTimeout (which implicitly requires an event loop), explicit introspection/management of the event loop, and support for other nodeJS APIs. These often seem to get mixed up and/or combined.

I would like to state that I believe that the first (support for setTimeout) should be part of the embedded JS runtime because it's part of every other JS runtime out there (including all the browsers). Lots of pure-JS things like Promises can be built on this.

The second thing (introspection and management of this loop) is something which could later be added, but I'm not sure it's expected so universally. (I don't personally need this.)

The last thing (general nodeJS APIs) is clearly a much larger endeavour here which should not be mixed up with the event loop which isn't node-specific afaics https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants