I need to close server after getting callback from /auth/github/callback
url. With usual HTTP API closing
server is currently supporting with server.close([callback])
API function, but with node-express server i’m getting TypeError: Object function app(req, res){ app.handle(req, res); } has no method 'close'
error. And I don't know how to find information to solve this problem.
How should I close express server?
NodeJS configuration notes:
$ node --version
v0.8.17
$ npm --version
1.2.0
$ npm view express version
3.0.6
Actual application code:
var app = express();
// configure Express
app.configure(function() {
// … configuration
});
app.get(
'/auth/github/callback',
passport.authenticate('github', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
setTimeout(function () {
app.close();
// TypeError: Object function app(req, res){ app.handle(req, res); } has no method 'close'
}, 3000)
}
);
app.listen('http://localhost:5000/');
Also, I have found ‘nodejs express close…’ but I don't sure if I can use it with code I have: var app = express();.
app.listen() returns http.Server. You should invoke close() on that instance and not on app instance.
Ex.
app.get(
'/auth/github/callback',
passport.authenticate('github', { failureRedirect: '/login' }),
function(req, res) {
res.redirect('/');
setTimeout(function () {
server.close();
// ^^^^^^^^^^^
}, 3000)
}
);
var server = app.listen('http://localhost:5000/');
// ^^^^^^^^^^
You can inspect sources: /node_modules/express/lib/application.js
In express v3 they removed this function.
You can still achieve the same by assigning the result of app.listen() function and apply close on it:
var server = app.listen(3000);
server.close((err) => {
console.log('server closed')
process.exit(err ? 1 : 0)
})
https://github.com/visionmedia/express/issues/1366
If any error occurs in your express app then you must have to close the server and you can do that like below-
var app = express();
var server = app.listen(process.env.PORT || 5000)
If any error occurs then our application will get a signal named SIGTERM. You can read more SIGTERM here - https://www.gnu.org/software/libc/manual/html_node/Termination-Signals.html
process.on('SIGTERM', () => {
console.info('SIGTERM signal received.');
console.log('Closing http server.');
server.close((err) => {
console.log('Http server closed.');
process.exit(err ? 1 : 0);
});
});
I have answered a variation of "how to terminate a HTTP server" many times on different node.js support channels. Unfortunately, I couldn't recommend any of the existing libraries because they are lacking in one or another way. I have since put together a package that (I believe) is handling all the cases expected of graceful express.js HTTP(S) server termination.
https://github.com/gajus/http-terminator
The main benefit of http-terminator is that:
it does not monkey-patch Node.js API
it immediately destroys all sockets without an attached HTTP request
it allows graceful timeout to sockets with ongoing HTTP requests
it properly handles HTTPS connections
it informs connections using keep-alive that server is shutting down by setting a connection: close header
it does not terminate the Node.js process
calling server.close does the job
server.close((err) => {
console.log('server closed')
process.exit(err ? 1 : 0)
})
also it is good to listen for system(user) signals and shutdown gracefully on them too, for that you should listen on both SIGTERM and SIGINT
const port = process.env.PORT || 5000;
const server = app.listen(port);
console.log(`listening on port:${port}`);
for (let signal of ["SIGTERM", "SIGINT"])
process.on(signal, () => {
console.info(`${signal} signal received.`);
console.log("Closing http server.");
server.close((err) => {
console.log("Http server closed.");
process.exit(err ? 1 : 0);
});
});
Old question but now Node v18.2.0 introduced server.closeAllConnections(). It should be noted that server.close never runs its callback when the browser sends the request Connection: keep-alive, because server.close only stops the server from accepting new connections, it does not close old connections.
Before Node v18.2.0 I tackled this problem by waiting 5 seconds for the server to shutdown, after which it would force exit.
This code encompasses both situations
process.on('SIGINT', gracefulShutdown)
process.on('SIGTERM', gracefulShutdown)
function gracefulShutdown (signal) {
if (signal) console.log(`\nReceived signal ${signal}`)
console.log('Gracefully closing http server')
// closeAllConnections() is only available from Node v18.02
if (server.closeAllConnections) server.closeAllConnections()
else setTimeout(() => process.exit(0), 5000)
try {
server.close(function (err) {
if (err) {
console.error('There was an error', err)
process.exit(1)
} else {
console.log('http server closed successfully. Exiting!')
process.exit(0)
}
})
} catch (err) {
console.error('There was an error', err)
setTimeout(() => process.exit(1), 500)
}
}
Most answers call process.exit(), I don't think this is a good idea. You probably need to perform some teardown, also it's simply not needed.
const server = app.listen(port);
server.on('close', () => {
// Perform some teardown, for example with Knex.js: knex.destroy()
});
// FYI Docker "stop" sends SIGTERM
// If SIGTERM is not catched, Docker is forced to kill the container after ~10s
// and this provokes an exit code 137 instead of 0 (success)
process.on('SIGTERM', () => server.close());
Check Express.js 4.x documentation: https://expressjs.com/en/advanced/healthcheck-graceful-shutdown.html#graceful-shutdown
Related
I am mocking some endpoints of the Kubernetes API in a mock server for some integration tests and got stuck in the implementation of the endpoint /apis/batch/v1/watch/namespaces/{namespace}/jobs?watch=true (doc, need to search for batch/v1/watch in the page). The client uses this method to make a GET request and keep the connection open to receive events related to Job resources. Apparently, it handles a 'socket' event.
I implemented a simple mock endpoint that returns the data I want, but I get this error when the request is made:
Error: socket hang up
at connResetException (node:internal/errors:691:14)
at Socket.socketOnEnd (node:_http_client:466:23)
at Socket.emit (node:events:538:35)
at endReadableNT (node:internal/streams/readable:1345:12)
at processTicksAndRejections (node:internal/process/task_queues:83:21)
How should this mock be implemented? Do I need to return a socket? How should I do that?
Answering to my own question: after some attempts, all I needed to do was to use res.write() with a string that ends with a line break character, like this:
import express from 'express';
const TIME_BETWEEN_EVENTS = 500; // Milliseconds
const app = express();
app.get('/apis/batch/v1/watch/namespaces/:namespace/jobs', (_, res) => {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
Connection: 'keep-alive',
});
console.log('Client connected to Jobs watch endpoint');
let jobEventsSent = 0;
const interval = setInterval(() => {
if (jobEventsSent < 3) {
console.log('Sending data to Jobs watcher');
res.write(
Buffer.from(JSON.stringify({ type: 'ADDED', object: { /* Job Resource */ } }) + '\n'),
);
jobEventsSent++;
} else {
clearInterval(interval)
}
}, TIME_BETWEEN_EVENTS);
res.socket.on('close', () => {
console.log('Client disconnected from Jobs watch endpoint');
if (interval) clearInterval(interval);
});
});
The code above keeps the connection alive event after all the messages have been sent. To close the connection, it is necessary to call res.end();
I am trying to build/deploy a tracker server for use with P2P applications using the below code. It works fine locally, but when I deploy it to Heroku, the port bindings fail because only one port is allowed.
// Create a web sockets signaling server
var express = require('express');
var bodyParser = require('body-parser');
var app = express();
//Allow all requests from all domains & localhost
app.all('/*', function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "POST, GET");
next();
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
let lookup = {}
const hostname = '0.0.0.0';
const port = process.env.PORT;
var Server = require('bittorrent-tracker').Server
var server = new Server({
udp: false, // enable udp server? [default=true]
http: true, // enable http server? [default=true]
ws: true, // enable websocket server? [default=true]
stats: true, // enable web-based statistics? [default=true]
})
server.on('error', function (err) {
// fatal server error!
console.log(err.message)
})
server.on('warning', function (err) {
// client sent bad data. probably not a problem, just a buggy client.
console.log(err.message)
})
server.on('listening', function () {
// fired when all requested servers are listening
console.log('Signal server http port:' + server.http.address().port)
console.log('Signal server ws port:' + server.ws.address().port)
})
// start tracker server listening! Use 0 to listen on a random free port.
server.listen(port, hostname, 'listening')
// listen for individual tracker messages from peers:
server.on('start', function (addr) {
console.log('got start message from ' + addr)
Object.keys(server.torrents).forEach(hash => {
lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
console.log("peers: " + server.torrents[hash].peers.length)
})
})
server.on('complete', function (addr) {})
server.on('stop', function (addr) {})
app.get('/peers', function(req, res) {
res.send(lookup);
})
app.listen(process.env.PORT, function() {
console.log('Express server port: ' + this.address().port); //Listening on port #
})
If I use process.env.PORT for both server and app, I get the following, which is expected since Heroku only allows 1 listen port:
2021-02-13T05:35:31.016101+00:00 heroku[web.1]: State changed from starting to up
2021-02-13T05:35:30.885170+00:00 app[web.1]: Express server port: 9898
2021-02-13T05:35:30.885204+00:00 app[web.1]: listen EADDRINUSE: address already in use 0.0.0.0:9898
2021-02-13T05:35:30.885205+00:00 app[web.1]: listen EADDRINUSE: address already in use 0.0.0.0:9898
If I hard code the port for either server or app, the application launches fine, but the signaling server doesn't work. No substantial logging is generated.
2021-02-13T05:38:21.141806+00:00 heroku[web.1]: State changed from starting to up
2021-02-13T05:38:20.998054+00:00 app[web.1]: Express server port: 25702
2021-02-13T05:38:20.998550+00:00 app[web.1]: Signal server http port:31415
2021-02-13T05:38:20.998683+00:00 app[web.1]: Signal server ws port:31415
Is it possible that the bittorrent-tracker server and express server can use the same port? For instance, could I get and return the list of peers within this block of code without the need for express at all?
server.on('start', function (addr) {
console.log('got start message from ' + addr)
// Could I do something here to eliminate the need for Express?
Object.keys(server.torrents).forEach(hash => {
lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
console.log("peers: " + server.torrents[hash].peers.length)
})
})
The documentation states:
The http server will handle requests for the following paths:
/announce, /scrape. Requests for other paths will not be handled.
But perhaps there is some way I can shim in the requests that express is handling?
Not long after asking this question, it occurred to me that I might not need express at all. It turns out that was correct.
For anyone wanting a Heroku-ready bittorrent-tracker, here is the updated code:
// Create a web sockets signaling server
let lookup = {}
const hostname = '0.0.0.0';
const port = process.env.PORT;
var Server = require('bittorrent-tracker').Server
var server = new Server({
udp: false, // enable udp server? [default=true]
http: true, // enable http server? [default=true]
ws: true, // enable websocket server? [default=true]
stats: true, // enable web-based statistics? [default=true]
})
server.on('error', function (err) {
// fatal server error!
console.log(err.message)
})
server.on('warning', function (err) {
// client sent bad data. probably not a problem, just a buggy client.
console.log(err.message)
})
server.on('listening', function () {
// fired when all requested servers are listening
console.log('Signal server http port:' + server.http.address().port)
console.log('Signal server ws port:' + server.ws.address().port)
})
// start tracker server listening! Use 0 to listen on a random free port.
server.listen(port, hostname, 'listening')
// listen for individual tracker messages from peers:
server.on('start', function (addr) {
console.log('got start message from ' + addr)
Object.keys(server.torrents).forEach(hash => {
lookup[server.torrents[hash].infoHash] = server.torrents[hash].peers.length
console.log("peers: " + server.torrents[hash].peers.length)
})
})
server.on('complete', function (addr) {})
server.on('stop', function (addr) {})
I've started a project that requires communication between an arduino and a local nodejs server (unrelated the data will be sent via an http request or a socket to the actual remote server later on). I'm using the node package serialport. At the beginning of the serial communication, the server needs to "find" the arduino. I've decided on the following negotiation codex:
1) the server sends a "c" character (as in connect) which the arduino is listening for
2) the arduino replies to all "c"s with another "c" which the server will be listening for
in other words when both sides receive a "c" that means the serial connection works
However, due to serialport using promises I can't go through all available ports and check if there's an arduino (which replies with "c") there.
Here's what I've come up with so far:
var SerialPort = require('serialport');
var Readline = require('#serialport/parser-readline');
async function tryPort(path) {
var port = new SerialPort(path, {
baudRate: 9600
});
port.on('error', function (err) {
console.log(err);
});
port.pipe(new Readline({ delimiter: '\n' })).on('data', (data)=>{
console.log(port);
console.log(data);
if (data == 'c') {
return port;
}
port.close();
});
port.write("c", function (err) {
if (err) console.log(err);
});
}
async function connect() {
var connection, ports = await SerialPort.list();
for(i=0;i<ports.length;i++){
connection = await tryPort(ports[i].path);
}
setTimeout(() => {
if (!connection) {
console.log("no port/response found");
}else{
console.log(connection);
}
}, 3000);
}
connect();
I went with the assumption the variable 'connection' will be assigned the value of the port that responded correctly last because that port will take the longest to finish. Unfortunately, it seems this won't work with promises... So I'm wondering if there's any other way to accomplish it?
I setup my REST server with express.js. Now I want to add sse to this server. After I implemented this sse package, I get an error. I know that I get this error, when would try to use res.send twice, but I am not.
ERROR: Error: Can't set headers after they are sent.
at ServerResponse.OutgoingMessage.setHeader (http.js:690:11)
at ServerResponse.header (/home/root/node_modules/express/lib/response.js:718:10)
at ServerResponse.send (/home/root/node_modules/express/lib/response.js:163:12)
at app.get.str (/home/root/.node_app_slot/main.js:1330:25)
at Layer.handle [as handle_request] (/home/root/node_modules/express/lib/router/layer.js:95:5)
at next (/home/root/node_modules/express/lib/router/route.js:131:13)
at sse (/home/root/node_modules/server-sent-events/index.js:35:2)
at Layer.handle [as handle_request] (/home/root/node_modules/express/lib/router/layer.js:95:5)
at next (/home/root/node_modules/express/lib/router/route.js:131:13)
at Route.dispatch (/home/root/node_modules/express/lib/router/route.js:112:3)
Is it possible that I can't use the express methods anymore within the sse function? For example:
app.get('/events', sse, function(req, res) {
res.send('...');
});
Furthermore, I found this solution and this. Is it possible to make sse with the res.write function or in another way without using another package?
I disagree with using Socket.IO to implement basic Server-Sent Events. The browser API is dead simple and the implementation in Express requires only a couple of changes from a normal response route:
app.get('/streaming', (req, res) => {
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Connection', 'keep-alive');
res.flushHeaders(); // flush the headers to establish SSE with client
let counter = 0;
let interValID = setInterval(() => {
counter++;
if (counter >= 10) {
clearInterval(interValID);
res.end(); // terminates SSE session
return;
}
res.write(`data: ${JSON.stringify({num: counter})}\n\n`); // res.write() instead of res.send()
}, 1000);
// If client closes connection, stop sending events
res.on('close', () => {
console.log('client dropped me');
clearInterval(interValID);
res.end();
});
});
Set the appropriate headers as per the spec
Use res.flushHeaders() to establish SSE connection
Use res.write() instead of res.send() to send data
To end stream from the server, use res.end()
The snippet above uses setInterval() to simulate sending data to the client for 10 seconds, then it ends the connection. The client will receive an error for the lost connection and automatically try to re-establish the connection. To avoid this, you can close the client on error, or have the browser send a specific event message that the client understands means to close gracefully. If the client closes the connection, we can catch the 'close' event to gracefully end the connection on the server and stop sending events.
express: 4.17.1
node: 10.16.3
You can definitely achieve this without other packages.
I wrote a blog post about this, part 1 sets out the basics.
You mustn't close the SSE as that breaks the functionality. The whole point is that it is an open HTTP connection. This allows for new events to be pushed to the client at any point.
This adds a complete, runnable example (with client to read the stream) to John's excellent answer and makes a tweak, adding the Connection: keep-alive header.
server.js:
const express = require("express");
const fs = require("fs").promises;
const path = require("path");
const app = express();
app
.set("port", process.env.PORT || 5000)
.get("/", (req, res) => {
fs.readFile(path.join(__dirname, "client.html"))
.then(file => res.send(file.toString()))
.catch(err => res.status(404).send(err.message))
;
})
.get("/stream", (req, res) => {
res.set({
"Access-Control-Allow-Origin": "*",
"Cache-Control": "no-cache",
"Connection": "keep-alive",
"Content-Type": "text/event-stream",
});
res.flushHeaders();
let counter = 0;
const interval = setInterval(() => {
res.write("" + counter++);
}, 1000);
res.on("close", () => {
clearInterval(interval);
res.end();
});
})
.listen(app.get("port"), () =>
console.log(`server listening on port ${app.get("port")}`)
)
;
client.html:
<!DOCTYPE html>
<html lang="en">
<head></head>
<body>
<script>
(async () => {
const response = await fetch("/stream");
if (!response.ok) {
throw Error(response.status);
}
for (const reader = response.body.getReader();;) {
const {value, done} = await reader.read();
if (done) {
break;
}
document.body.innerText = new TextDecoder().decode(value);
}
})();
</script>
</body>
</html>
After node server.js, navigate your browser to localhost:5000. You can also test the stream directly with curl localhost:5000/stream.
I won't repeat the notes from John's answer, but, in short we set the necessary headers and flush them to begin the connection, then use res.write to send a chunk of data. Call res.end() to terminate the connection on the server or listen for res.on("close", ...) for the client closing the connection.
The client uses fetch and response.body.getReader() which can be read with const {value, done} = await reader.read() and decoded with TextDecoder().decode(value).
See also https://masteringjs.io/tutorials/express/server-sent-events
Express 4.17.1, Node 15.2.0, Chrome 89.0.4389.128 (Official Build) (64-bit)
It appears from the documentation on the library you're using that you should use a res.sse when using that as middleware on a function. See:
https://www.npmjs.com/package/server-sent-events
But, all this is actually doing from their code is wrapping res.write as you mentioned. See:
https://github.com/zacbarton/node-server-sent-events/blob/master/index.js#L11
Self-promotion: I wrote the ExpreSSE package that provides middlewares for working with SSE in express, you can find it on npm: #toverux/expresse.
A simple example:
router.get('/events', sse(/* options */), (req, res) => {
let messageId = parseInt(req.header('Last-Event-ID'), 10) || 0;
someModule.on('someEvent', (event) => {
//=> Data messages (no event name, but defaults to 'message' in the browser).
res.sse.data(event);
//=> Named event + data (data is mandatory)
res.sse.event('someEvent', event);
//=> Comment, not interpreted by EventSource on the browser - useful for debugging/self-documenting purposes.
res.sse.comment('debug: someModule emitted someEvent!');
//=> In data() and event() you can also pass an ID - useful for replay with Last-Event-ID header.
res.sse.data(event, (messageId++).toString());
});
});
There is also another middleware to push the same events to multiple clients.
New Answer:
Just use socket.io, it's so much easier and better!
https://www.npmjs.com/package/socket.io#in-conjunction-with-express
basic setup:
const express = require('express');
const PORT = process.env.PORT || 5000;
const app = express();
const server = require('http').createServer(app);
const io = require('socket.io')(server);
// listen to socket connections
io.on('connection', function(socket){
// get that socket and listen to events
socket.on('chat message', function(msg){
// emit data from the server
io.emit('chat message', msg);
});
});
// Tip: add the `io` reference to the request object through a middleware like so:
app.use(function(request, response, next){
request.io = io;
next();
});
server.listen(PORT);
console.log(`Listening on port ${PORT}...`);
and in any route handler, you can use socket.io:
app.post('/post/:post_id/like/:user_id', function likePost(request, response) {
//...
request.io.emit('action', 'user liked your post');
})
client side:
<script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-1.11.1.js"></script>
<script>
$(function () {
var socket = io();
$('form').submit(function(e){
e.preventDefault(); // prevents page reloading
socket.emit('chat message', $('#m').val());
$('#m').val('');
return false;
});
socket.on('chat message', function(msg){
$('#messages').append($('<li>').text(msg));
});
});
</script>
full example: https://socket.io/get-started/chat/
Original Answer:
Someone (user: https://stackoverflow.com/users/451634/benny-neugebauer | from this article: addEventListener on custom object) literally gave me a hint on how to implement this without any other package except express! I have it working!
First, import Node's EventEmitter:
const EventEmitter = require('events');
Then create an instance:
const Stream = new EventEmitter();
Then create a GET route for event streaming:
app.get('/stream', function(request, response){
response.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
Stream.on("push", function(event, data) {
response.write("event: " + String(event) + "\n" + "data: " + JSON.stringify(data) + "\n\n");
});
});
In this GET route, you are writing back that the request is 200 OK, content-type is text/event-stream, no cache, and to keep-alive.
You are also going to call the .on method of your EventEmitter instance, which takes 2 parameters: a string of the event to listen for and a function to handle that event(that function can take as much params as it is given)
Now.... all you have to do to send a server event is to call the .emit method of your EventEmitter instance:
Stream.emit("push", "test", { msg: "admit one" });
The first parameter is a string of the event you want to trigger (make sure that it is the same as the one in the GET route). Every subsequent parameter to the .emit method will be passed to the listener's callback!
That is it!
Since your instance was defined in a scope above your route definitions, you can call the .emit method from any other route:
app.get('/', function(request, response){
Stream.emit("push", "test", { msg: "admit one" });
response.render("welcome.html", {});
});
Thanks to how JavaScript scoping works, you can even pass that EventEmitter instance around to other function, even from other modules:
const someModule = require('./someModule');
app.get('/', function(request, response){
someModule.someMethod(request, Stream)
.then(obj => { return response.json({}) });
});
In someModule:
function someMethod(request, Stream) {
return new Promise((resolve, reject) => {
Stream.emit("push", "test", { data: 'some data' });
return resolve();
})
}
That easy! No other package needed!
Here is a link to Node's EventEmitter Class: https://nodejs.org/api/events.html#events_class_eventemitter
My example:
const EventEmitter = require('events');
const express = require('express');
const app = express();
const Stream = new EventEmitter(); // my event emitter instance
app.get('/stream', function(request, response){
response.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive'
});
Stream.on("push", function(event, data) {
response.write("event: " + String(event) + "\n" + "data: " + JSON.stringify(data) + "\n\n");
});
});
setInterval(function(){
Stream.emit("push", "test", { msg: "admit one" });
}, 10000)
I am running node + express + mongojs. Here is a sample code:
function mongoCallback(req, res) {
"use strict";
return function (err, o) {
if (err) {
res.send(500, err.message);
} else if (!o) {
res.send(404);
} else {
res.send(o);
}
};
}
var express, app, params, mongo, db;
express = require('express');
params = require('express-params');
app = express();
params.extend(app);
app.use("/", express.static('web'));
mongo = require('mongojs');
db = mongo.connect('mydb', ['inventory']);
app.get('/api/inventory', function (req, res) {
db.inventory.find(mongoCallback(req, res));
});
app.listen(8000);
console.log('Listening on port 8000');
Sometimes I forget running mongod and an attempt to talk to the database fails with "failed to connect to ..." error. The problem is that starting mongod is not enough, the already existing db object seems to remember that no connection could be made and so the server continues to fail, even if mongod is already running.
So, I have come up with the following solution:
var express, app, params, mongo, db, api;
if (!String.prototype.startsWith) {
String.prototype.startsWith = function (str) {
"use strict";
return this.lastIndexOf(str, 0) === 0;
};
}
function setDB() {
db = mongo.connect('IF', ['invoices', 'const', 'inventory']);
}
function mongoCallback(req, res, next, caller, secondTry) {
return function (err, o) {
if (err) {
if (!secondTry && err.message && err.message.startsWith("failed to connect to")) {
setDB();
caller(req, res, next, true);
} else {
res.send(500, err.message);
}
} else if (!o) {
res.send(404);
} else {
res.send(o);
}
};
}
express = require('express');
params = require('express-params');
app = express();
params.extend(app);
app.use("/", express["static"]('web'));
mongo = require('mongojs');
setDB();
api = {
getInventory: function (req, res, next, secondTry) {
db.inventory.find(mongoCallback(req, res, next, api.getInventory, secondTry));
}
};
app.get('/api/inventory', api.getInventory);
app.listen(8000);
console.log('Listening on port 8000');
Basically it recreates the db object if a request fails with the "failed to connect to" error and reruns the request. This is done only for the first failure. A subsequent failure returns the error.
I do not like my solution at all. There has to be a better way. Any suggestions?
Thanks.
What do you mean by "the already existing db object seems to remember that no connection could be made"? Do you mean that the queries on the database fail if you start the express app before running mongod? Since you are connecting to the DB at the startup of the express app, you should have the mongod running first.
If you are worried about the database going down after the initial connection and causing your CRUD operations to fail, you can check for an error in your operations
db.inventory.find(function(err, docs) {
// check err to see if there was a connection issue
});
and then reconnect if there was an error.
As far as I know the mongodb native driver allows to set { auto_reconnect:true }, have you tried to set this?
I'm not sure how this behaves if the database wasn't running at all, mongoose.js for example caches all requests until the DB is ready and issues them after a successful connection.