Why is my Node.js service stopping unexpectedly under GraalVM? - node.js

I have a fairly simple Node.js service that basically just fields a few HTTP requests. This runs fine via the GraalVM node command. However, when I use node --jvm --polyglot service.js My Node service dies shortly after starting. Nothing else in the code has changed.
What is interesting is that the following code seems to kill my Node.js service
const { MongoClient } = require("mongodb")
console.log("got MongoClient")
And when I run Graal Node without --jvm --polyglot everything works fine.
If I comment out the Mongo stuff, running with --jvm --polyglot, everything works fine.
What could possibly be going on where trying to run the MongoDB Node.js driver under GraalVM could be causing problems?
It may not be that it dies, but after starting my HTTP service
const server = app.listen(port, () => console.log(`Server running... test at http://${hostname}:${port}/ping`))
it no longer accepts HTTP requests. ???

The best approach would be to raise an issue on GraalVM's repos, probably on the Graal.js one: https://github.com/oracle/graaljs. It could be a bug.
You can also debug the process and maybe that will reveal additional details of what's happening: https://www.graalvm.org/tools/chrome-debugger/

Related

Requiring an Express app in a Mocha Test file starts the server itself

Brief : While writing tests in Mocha for an Express driven RESTful HTTP API using Supertest, it's known we have to require an instance of the express app. However, this require statement is apparently the root cause for an open connection after the tests have finished and cleaned up. This is a bizarre situation and unexpected totally.
Background : The repository in question is on GitHub at sakshamsaxena/uzay [1]
The tests are typical in syntax to that recommended by Super Test itself. The request creates the server and the callback passed to expect closes the server. This was verified by adding console.log lines to the library file in node_modules. It is verified that all the connections were gracefully closed and tests passed alright. No other notification/warning anything was encountered during this, but Mocha never exited on it's own. I am well aware about the Mocha 4+ behavior and investigated this using WTFNode. On SIGINT, it was noticed[2][3] that an app instance is still alive. Naturally, I double checked this by commenting out all tests and running the suite again with WTFNode, only to encounter the exact same message. Right now, the test has no real test, just pending tests, and 2 require statements [4] where one of those is clearly the culprit. What is happening/what am I doing wrong ?
References :
[1] : https://github.com/sakshamsaxena/uzay/
[2] :
[WTF Node?] open handles:
- File descriptors: (note: stdio always exists)
- fd 1 (stdio)
- fd 2 (stdio)
- Servers:
- :::3000 (HTTP)
- Listeners:
- request: app #
D:\Personal\uzay\node_modules\express\lib\application.js:617
[3] : https://github.com/myndzi/wtfnode/blob/a080e019f06187aa1e762ac9025bd22430d4129c/index.js#L512
[4] :
const request = require('supertest')
const app = require('../index.js')
Question : Requiring the express server isn't supposed to run the server. Without an explicit call to listen the server shouldn't have started, but it somehow does. Why does this happen? What could be the reason for this ?
You are requiring the root index.js in your tests. require() in fact do evaluate the whole js file, thus the .listen() call will be run.
You can solve the problem by setting an environment variable that would be set only when running test, say, process.env.CI. Then
if (!process.env.CI) {
app.listen(3000, function () {
console.log('Uzay live on port 3000!')
})
}

How to close angular server from nodejs?

I am making a web page using angular 6.0.8 with the cli too. I was able to successfully start the server using nodejs Child Process like this
var child=children.exec("ng serve",{},function(error,stdin,stdout){
console.log('server terminated: '+error);
});
Then when I try to close the server like this
child.kill("SIGKILL");
It cuts off the connection between the server and my nodejs program but the server doesnt actually close until the host nodejs program does even thought the child process now registers as killed. I also tried to close it by connecting to the readline of the child process but that seemed to just cause more errors. this is what I tried
var childrl=readline.createInterface({stdin:child.stdin,stdout:child.stdout});
childrl.write(null,{ctrl:true,name:"c"});
the error it gave me is that input.on is not a function.
Try using Node.JS's child_process to spawn a new process something like below:-
var angular = require('child_process').spawn('ng', ['serve']);
When you need to close the angular server, you may use something like below:-
angular.kill('SIGINT');
Hope it helps.

Why I am able to access mongodb without running local mongo server?

I am beginning with server side programming by following a online course. As per my understanding, we use mongoose.connect(url) to connect to mongodb where url can be localhost url on which mongodb server is running.
But recently I forgot to run the local mongodb server using mongod. When I ran my node app with following code, it worked just fine :
var mongoose = require('mongoose');
mongoose.Promise = global.Promise;
mongoose.connect(process.env.MONGO_URL || 'mongodb://localhost:27017/TodoApp');
const {Todo} = require('./../server/models/todos');
const {ObjectID} = require('mongodb');
Todo.remove({}).then((result)=>{
console.log(result);
});
It worked fine with no error even though mongodb server was not running. When I checked the local database using Robo-3T tool, the documents were removed. I have verified this again.
I am unable to understand why my node app was able to connect to mongodb://localhost:27017/TodoApp even though mongodb server was not running on localhost:27017. Also, why Robo-3T tool was able to connect to this localhost: 27017 if server was not running.
Thanks.
The mongodb server was already running. Looks like the server does not shuts down on closing the terminal. It still runs in background. We have to close it using Ctrl+C.
More info: mongodb doesn't stop when I close terminal
Thanks #Sergio Tulentsev.
The reason is simple, the process is running in the background. If you search for 'services' - (in windows), scroll down to check for MongoDb, you will see that the process is running (Started). If set to Automatic, it starts up even after every restart.
Another reason is MongoDB server runs as a service in the background. Even if you restart your computer, it may be running.
I recognized at my win 10, MongoDB server is automatically started. So, you don't need to run mongod on your local.
At win 10 you can check it by:
type services in the search box;
open Services window;
Find MongoDB Server in the list;
Check Startup Type.
Probably your startup type is Automatic, you can change MongoDB Server startup type here.
It occurs when you don't stop the server explicitly and close your terminal.The server is running in background.You can see that in your task manager as well. Press Ctrl+C to quit and it will stop your server.

Service Fabric node.js guest application express.js server EADDRINUSE

Not sure if this is a service fabric issue, or issue with node.js.
Basically this is my problem. I deploy the node.js application, it works fine. I redeploy the node application it fails to work, with the server returning EADDRINUSE. When I run netstat -an the port isn't in use. It's as if node is still running somewhere, some how, but not appearing in tasklist etc..
Anyone got any ideas?
Not entirely sure, but I believe this is because the server I was using (express.js), or rather node, was not shutting down and closing existing connections causing windows to think the ports are still in use. At least, that's how it seems.
I can not find it "officially" documented, but from this (quoted below) it reads SF sends SIGINT to the application to attempt to end it before killing it.
The following code appears to fix my issue:
var app = express();
var server = app.listen(17500);
if (process.platform === "win32") {
var rl = require("readline").createInterface({
input: process.stdin,
output: process.stdout
});
rl.on("SIGINT", function () {
process.emit("SIGINT");
}
}
process.on("SIGINT", function() {
server.close(function () {
process.exit(0);
});
});
For Linux nodes, I suppose you'd want to listen for "SIGTERM" as well.
I would like to know if there's any sort of remediation for this though, in the previously mentioned scenario the VMSS was completely unusable -- I could not deploy, nor run, a node web server. How does one restart the cluster without destroying it and recreating it? I now realise you can't just restart VMSS instances willy-nilly because service fabric completely breaks if you do that, apparently irrevocably
Rajeet Nair [RajeetN#MSFT]
Service Fabric also sends a Ctrl-C to service processes and waits for service to terminate. If the service doesn't terminate for 3 minutes, the process is killed.

Shutting down a Node.js http server in a unit test

Supposed I have some unit tests that test a web server. For reasons I don't want to discuss here (outside scope ;-)), every test needs a newly started server.
As long as I don't send a request to the server, everything is fine. But once I do, a call to the http server's close function does not work as expected, as all made requests result in kept-alive connections, hence the server waits for 120 seconds before actually closing.
Of course this is not acceptable for running the tests.
At the moment, the only solutions I'd see was either
setting the keep-alive timeout to 0, so a call to close will actually close the server,
or to start each server on a different port, although this becomes hard to handle when you have lots of tests.
Any other ideas of how to deal with this situation?
PS: I had a asked How do I shutdown a Node.js http(s) server immediately? a while ago, and found a viable way to work around it, but as it seems this workaround does not run reliably in every case, as I am getting strange results from time to time.
function createOneRequestServer() {
var server = http.createServer(function (req, res) {
res.write('write stuff');
res.end();
server.close();
}).listen(8080);
}
You could also consider using process to fork processes and kill them after you have tested on that process.
var child = fork('serverModuleYouWishToTest.js');
function callback(signalCode) {
child.kill(signalCode);
}
runYourTest(callback);
This method is desirable because it does not require you to write special cases of your servers to service only one request, and keeps your test code and your production code 100% independant.

Resources