nodejs / user-feedback

Node.js User Feedback Initiative
https://github.com/nodejs/user-feedback
56 stars 18 forks source link

Form team/group to define "embedding requirements" #51

Open mhdawson opened 6 years ago

mhdawson commented 6 years ago

There is ongoing work to allow Node.js to be built as a static or shared library. This allows Node.js to be embedded in the process of another application. See https://github.com/nodejs/node/issues/14158, which is also being backported to 8.X and 6.X (https://github.com/nodejs/node/pull/19047, https://github.com/nodejs/node/pull/19050).

@yhwang is currently working on adding testing to the CI. That testing, however, will just be to make sure that the existing Node.js tests cases pass when using the static/shared library.

After that, we will want to add testing that covers typical use cases related to embedding Node.js into an application using either the static or shared libraries. I believe as part of that we'll also find that there are still some things missing. I just ran across this PR https://github.com/nodejs/node/pull/19005 which aims to address some of those kinds of things.

At this point, I'm wondering if there is enough interest to form a group that would work together or a number of months (maybe more) on defining and validating the different embedding use cases. The work would likely be:

@yhwang @nodejs/delivery-channels @addaleax @luminosuslight, @cmfcmf, @Hannes01071995, @justus-hildebrand, @msoechting @nodejs/tsc @dshaw

mhdawson commented 6 years ago

@groundwater I was hoping you might be interested in this, wondering if you go the ping through @nodejs/delivery-channels

rogerwang commented 6 years ago

Thanks for CCing. We NW.js maintainers would like to keep an eye on this. Though we just released NW.js 0.30.1 with Node.js 10.0.0 within 24 hours, rebasing with latest Node.js is still a significant effort. We are interested in this topic on how to integrate Node more easily.

mhdawson commented 6 years ago

@rogerwang thanks for replying, will include you when we get things rolling

groundwater commented 6 years ago

Hi @mhdawson. Thanks for this! We have a number of folks at JSConf EU, and I believe there is a node's summit occurring shortly beforehand. Would it be worth sending a few of our folks to kick this discussion off in-person?

MylesBorins commented 6 years ago

I think having folks at the summit would be awesome!

On Fri, Apr 27, 2018, 11:53 AM Jacob Groundwater notifications@github.com wrote:

Hi @mhdawson https://github.com/mhdawson. Thanks for this! We have a number of folks at JSConf EU, and I believe there is a summit occurring shortly beforehand. Would it be worth sending a few of our folks to kick this discussion off in-person?

— You are receiving this because you are on a team that was mentioned. Reply to this email directly, view it on GitHub https://github.com/nodejs/user-feedback/issues/51#issuecomment-385013637, or mute the thread https://github.com/notifications/unsubscribe-auth/AAecV7sxNVOg_xqfGPx2b0LqaasSzJ4dks5tsz79gaJpZM4TSdYW .

kapouer commented 6 years ago

Hello, yesterday i enabled the --shared flag on node 10 debian package. Worked perfectly and this is really cool. I think make install should continue to install the executable (the one linked to the built lib) though. Not yet ready on my side, but it's going to bring a lot of improvements with respect to packaged addons, and multiarch support in debian. I'll follow up on issues tracker if necessary. I wish i could share my enthousiasm regarding how nodejs has matured and is getting easier and easier to distribute...

mhdawson commented 6 years ago

@groundwater I don't necessarily want to wait to start discussing and possibly meeting remotely until after the summit (not everybody will be at the summit either), but getting together in person at the summit would be great.

groundwater commented 6 years ago

@mhdawson agreed. Would you like to kick this off asynchronously or via a synchronous video discussion?

addaleax commented 6 years ago

I’d definitely like to be involved in this, yes.

Also, maybe /cc @fs-eire … please let me know if this is not the kind of thing you want to be pinged in, but it sounded like you might be somebody who wants to be aware that this is happening?

mhdawson commented 6 years ago

I think starting with a video call to get together to review what I suggested above as the way forward and to agree on the best way to work together (github, regular meetings or whatever). I'll get together with @yhwang to set up a kickoff meeting.

mhdawson commented 6 years ago

@gireeshpunathil FYI.

davicrig commented 6 years ago

We currently embed the shared library in IBM Integration Bus, we recently updated in quick succession from node 4 through 6 to node 8 and found the upgrade process pretty painful so anything we can do to help stabilise the interfaces or improve our own integration would be a benefit to us.

We are a bit unusual in that we also embed a JVM and on windows platforms a CLR as well so we may have some use cases / problems that other users do not so might bring some different use cases to the table.

mhdawson commented 6 years ago

@davicrig sounds good, your insight will be valuable.

yhwang commented 6 years ago

With @mhdawson help, we plan to have a conference call to discuss about the shared lib usage and try to form the group for embedding users. Here is the agenda:

================================

Feel free to add item into the agenda for discussion.

I created a doodle poll for the conference call ==> https://doodle.com/poll/tamxygwfsgh5dr5w. Please select your available time slots then we may select a proper time for the conference call once the most people who are interested in vote.

mhdawson commented 6 years ago

@gabrielschulhof adding you as an FYI as from your comments in a different issue I'm hoping you are interested in participating here as well.

rkaw92 commented 6 years ago

Hey, just letting you know that there's a project that embeds .NET in Node but also the other way around. Perhaps it can provide some additional usage context. https://github.com/tjanczuk/edge

NathanaelA commented 6 years ago

I'd like to add that https://github.com/janeasystems/nodejs-mobile is a project that allows you to embed node into Android/iOS application; Jaime @jaimecbernardo, might be interested in this; as I believe it would simplify updates if this was a consistent interface.

mhdawson commented 6 years ago

@addaleax if you can make one of the proposed times can you fill out the doodle?

mhdawson commented 6 years ago

@groundwater can you fill out the doodle?

mhdawson commented 6 years ago

@rogerwang can you fill out the doodle?

kapouer commented 6 years ago

Hi, in debian, it's considered to be "the right thing" to build (independently packaged) node addons against libnode-dev. I've enabled this with nodejs 10 debian package (which is sitting in experimental right now because many addons are still not compatible with node 10). This to emphasize shared lib builds are not only useful for embedders, but for distributors as well.

mhdawson commented 6 years ago

@kapouer are you talking about node.js as a shared library or things like openssl. The topic of this thread is the former.

kapouer commented 6 years ago

@mhdawson node.js as a shared library (which is as you point out, linked to other shared libs in debian).

yhwang commented 6 years ago

@kapouer I guess the libnode64 contains shared lib and libnode64-dev contains the header files. So distributors also care about the shared lib build as embedders. Thanks for the information.

yhwang commented 6 years ago

The poll result is 15:00 - 16:00 UTC/GMT this Thursday (17/May). Look forward to talking with you then. I will send out the invitation later.

rogerwang commented 6 years ago

Doodle was closed. Will try to attend on Thursday.

yhwang commented 6 years ago

@rogerwang sorry for that and welcome to join the discussion on Thursday. And here is the zoom that we will use for the meeting: https://zoom.us/webinar/134723812

codebytere commented 6 years ago

I'll be there :)

nitsakh commented 6 years ago

Great! I'll join the meeting on 17th May.

alexeykuzmin commented 6 years ago

I'll join on Thursday.

deepak1556 commented 6 years ago

I will also join the meeting on Thursday, Thanks!

jaimecbernardo commented 6 years ago

Me and @orangemocha from https://github.com/janeasystems/nodejs-mobile will also be joining on Thursday. Thank you!

yhwang commented 6 years ago

We got dropped because another community meeting was started I think. Sorry for that. Thank you for joining the discussion.

addaleax commented 6 years ago

I’d suggest creating a @nodejs/embedding team with everybody from today’s call in it, mostly as a way of being notified about relevant PRs/APIs. Does that sound okay? Alternatively, we could create the team and add a list of people who explicitly opt-in, if we’d expect it to be too much noise for some people.

gireeshpunathil commented 6 years ago

My observation from the first meeting is: potentially there are two ways to consolidate the embedding story:

The problem with the first approach is that the relevant re-enterable constituents (Platform, Environment, Isolate, libuv and Conetxt?) are singleton at the moment, so we don't know which of those are capable of recycling and re-entrance at the moment. Unless we test those through different uss cases we don't know the level of isolation they possess to the external world and between themselves.

So I propose we compile the existing and potential use cases as the first step, ratify their relevance, prioritize their impact and then address those in core through refactoring.

Scenarios that I am aware of:

Control flow:

Composition: [ I see many types of compositions are available when building from source, this covers the binaries that can be shipped ]

mhdawson commented 6 years ago

+1 to @gireeshpunathil's suggesion. I think capturing/documenting the use cases will provide a strong foundation to start with.

yhwang commented 6 years ago

@mhdawson @gireeshpunathil I think that's why we need the input from user perspective. Embedding users have their pain points and actually they also have their workaround. We should work together to integrate their solutions or enhance the node.js and make a better embedding experience.

@addaleax @nodejs/embedding is great. Can I create it?

@gireeshpunathil thanks for your input. we should put it into the use cases/pain points document.

I happened to have a family event after the meeting and just came back now. I will start to consolidate everyone's inputs in the meeting.

For @orangemocha, @jaimecbernardo, @alexeykuzmin, @nitsakh, @rogerwang, @fs-eire, @codebytere, @deepak1556 and @tdolby, can you provide your use cases and pain point in the comment and I will try to consolidate your input. Thanks.

addaleax commented 6 years ago

@addaleax @nodejs/embedding is great. Can I create it?

Sure, go ahead! If you can’t create teams because you’re not an org admin, just let me know.

rogerwang commented 6 years ago

@yhwang In NW.js we

  1. starts Node instance with different V8 settings for Chromium integration. The v8 settings calls are currently hardcoded in Node start process.
  2. starts/stops multiple Node instances in different threads; This enables Node.js working within Web Worker.
  3. looking for ways to load binary 3rd party Node modules, whose DLL currently have hard dependency on node.exe on Windows. It would be better to depend on something like node.dll.
orangemocha commented 6 years ago

@yhwang , from the perspective of nodejs-mobile:

Challenges / pain points:

  1. Lack of a reliable way to stop and restart the Node engine (though this has probably improved recently thanks to @addaleax 's work). This is not a show-stopper for the vast majority of use cases, because aside from performance considerations you can handle pretty much any task with a single Node instance servicing requests from the app via a messaging channel. However, it is a recurring ask from our users, probably because it is more convenient/natural to code an app that way. Also, we have encountered one use case where this features is critically important: there's a user who is developing a Node.js IDE for iPad; when running/launching your code, being able to restart the engine would be highly desirable. Note that on iOS we are not allowed to spawn Node in a separate process.
  2. Lack of documentation for the APIs to use in embedding scenarios.
  3. There are a few assumptions that Node APIs make about owning the process, that don't map too well to the embedded scenario. A simple answer here is to not use those APIs in mobile apps, but for some, a graceful adaptation might be useful:
    • console.log/error and process.stdout/stderr. In the plugins, we redirect these by default to platform-specific log streams. However this has the side effect of redirecting those streams for the entire process, potentially affecting other code in the app, which is not something you would expect from a library. It would be nice if Node's process.stdout/stderr streams could optionally be mapped to dedicated streams, however there are many places in Node and libuv where those are assumed to correspond to file descriptor 1 and 2.
    • process.exit. Again, you don't want a library to tear down the whole process. For this one, the best answer is probably to just avoid using it and eliminating the API on mobile, or making it throw an exception instead.
  4. Startup time can be problematic, and I am guessing this is more important to apps running on end-user devices rather than on a server. The problem is that Node apps/modules typically require a lot of small .js files, each with a synchronous round trip to a storage device. It is dramatically apparent on devices with slower storage drives. https://github.com/dominictarr/noderify is currently saving the day. I would love to see something like that make its way into Node core.
  5. Packaging/building modules. User modules are npm installed at build time and packaged with the app. This is not mandatory on all platforms, though I suspect that most apps would follow this model. I am not sure if this is a general embedding issue, but for iOS and Android this also means that npm install is performed on a host architecture different than the target architecture. This poses significant challenges for compiling native modules.
gireeshpunathil commented 6 years ago

@orangemocha - interesting scenarios!

Note that on iOS we are now allowed to spawn Node in a separate process.

did you mean not as opposed to now?

however there are many places in Node and libuv where those are assumed to correspond to file descriptor 1 and 2.

can't we solve this by simply redefining console.log and console.error and piping them to the desired streams before entering app code, or is it more complex than that?

orangemocha commented 6 years ago

@gireeshpunathil

did you mean not as opposed to now?

Yes :) Edited inline. Thanks.

can't we solve this by simply redefining console.log and console.error and piping them to the desired streams before entering app code, or is it more complex than that?

That is certainly feasible, and probably a fine solution. Currently we are redirecting the underlying process.stdout/stderr streams, but I have no knowledge of use cases out there that depend on those.

davicrig commented 6 years ago

Background

IBM Integration Bus is an Integration Platform provides a graphical programming environment for connecting disparate systems including transformation, enrichment, enhancement etc of inflight data flowing between these systems. User built applications are executed on a native C++ server process that also embeds a number of specific language runtimes (Java, .NET (on windows), nodejs.

Functional Use Cases

We embed the node.js engine to allow customer access to integration points that are accessible via node.js libraries. For example using the loopback framework. This includes marshalling / unmarshalling the data between our internal "message tree" format and javascript datatypes.

Executed node.js should be able to take advantage of the full JS ecosystem including modules that may have native dependencies.

Node dependencies are configured offline to deployment of the application using npm / node-gyp run in an external node process (ie/ the executable not the shared library.)

Building/Testing use cases

In order to support internal regression testing we also require the facility to execute arbitrary javascript code executed on the embedding node.js runtime (for example to test our integration layer and to provide integration testing on our connectors).

In order to support internal unit testing we test our own customer javascript using the usual frameworks chai / sinon etc and execute tests of pure JS code from an external node process.

We require code-coverage for our customer JS code and fail builds the reduce code coverage.

For the dependencies that we ship we run npm and by extension node-gyp as part of the build process.

Pain Points

The lifecycle of our major versions is much longer than the node.js lifecycle therefore we need to make major version updates within our release cycle. We have recently completed upgrade from node 4 to 6 and are in the process of moving to 8. In each case instability in the v8 API has lead us to need to rework the code which interfaces between the node.js engine and our C++ runtime.

Providing a stable API for embedding to would relieve the need for us to do this rework.

As part of an upgrade one of the significant issues we had was finding a way to ensure that our dependent node modules for both build and test were rebuild / recompiled with node-gyp, although this might belong in a different discussion we found that instability in many of the test framework APIs resulted in us having to make minor refactors to huge numbers of tests.

On windows we need to delay load the shared lib because native modules built by both the connectors that we ship and potentially user defined connectors contain the node executable name in their symbols. In order to prevent users having to recompile their modules just to work with us we needed to use dumpbin to export all the node executable symbols and redirect them to our own lib which we then chain to the shared lib.

Being able to remove this would remove considerable complexity to our build.

Since we are embedding the engine we expect to control the lifecycle of the node engine itself and any event loops / handles etc so that we can shutdown cleanly. During the upgrade to newer node versions we found that the shutdown process we were previously using did not work correctly. We eventually found that there were ways around this but a lack of documentation on object lifecycle made this very difficult for us.

Because we ship a JVM we have a reliance on certain signal handlers registered by the JVM and we have seen in the past that some node version register for -3. This in particular is problematic because this signal is used by the JVM to produce a javacore / heapdump which can be essential to diagnose problems in user supplied java code. We would ideally like the signal handlers used by the embedded node runtime to be documented and if possible have some more flexbility on which set of signals are used (for example something along the lines of https://www.ibm.com/support/knowledgecenter/en/SSYKE2_7.0.0/com.ibm.java.lnx.70.doc/diag/appendixes/cmdline/Xrs.html)

The node.js runtime is pretty opaque to us so we are not able to provide our users much operational information around the node runtime. For example we cant display how busy the event loops is, what the memory usage of the node engine is etc which means we do not have administrative feature parity with our other embedded runtimes.

We note that OpenSSL is statically linked to the node.js shared lib which makes the symbols available to the runtime loader on linux. Since we also ship OpenSSL (and consume other libraries which in term use OpenSSL) we are in a position where our code may end up using the node-provided symbols. If the OpenSSL versions differ between node.js and what we ship or if different global variables that share a name this can cause unknown behaviour. We increasingly have a need to update OpenSSL frequently to allow customers to mitigate exposure to high profile SSL attacks and we have imposed timelines on being able to make these upgrade. Decoupling from node version would help us significantly.

Having a long support lifecycle for a major version (minimum of 8 years) also puts us on a compiler upgrade treadmill if we want to maintain node currency especially on Visual Studio where we need to distribute additional runtime versions and where load-time binary compatibility between compiler versions seems to be weaker than gcc.

@gireeshpunathil also mentioned different icu options, we have seen similar symbol clashes with other third party binaries involving icu and our preference is for icu to be privately namespaced in a library.

mhdawson commented 6 years ago

@yhwang we should probably start planning the next meeting.

mhdawson commented 5 years ago

FYI @codebytere. @rubys is starting to get this started again (taking over from @yhwang). From your the presentation at the collaborator summit it sounds like you would want to be involved.

viferga commented 5 years ago

In my case I am building a high performance FaaS (Function as a Service) called MetaCall (https://metacall.io). For me it was necessary to have embedding API for NodeJS. But as it was not possible I managed to solve it myself.

I have add a detailed post in another issue (https://github.com/nodejs/node/issues/23265#issuecomment-452690239) detailing how I have achieved it. With the MetaCall library you can easily embed NodeJS in any language (not just C/C++).

I leave here the link to the repository (https://github.com/metacall/core). It may be interesting for NodeJS devs or other people looking to embed NodeJS.

mhdawson commented 5 years ago

@rubys would be great to move the formation of this group forward.

KevinEady commented 5 years ago

Hi @mhdawson ,

I've been doing some node embedding and development in my free time, focusing on integration with native C++ apps (and thereby using node-addon-api as well). I'm highly interested in where this goes, so I've subscribed to this issue. Is there anything else you would recommend I do so I can stay in the loop regarding node embedding and API changes? Not sure what this group is you mentioned, but I would love to contribute in any way possible (inputs for use-cases, testing apis, feedback, etc)

Thanks, Kevin

mhdawson commented 5 years ago

@Kevin thanks for the heads up. @rubys is away for a few weeks but when he gets back we'll see if we can get this initiative going again and then point info on participation in this issue.