discord.js how to send a detected memory leak to a channel? - memory-leaks

So i get a memory leak in console from my discord bot (discord.js), so is there a way to send a message in a channel when a memory leak happens?

try {
// code which causes memory leak here
}
catch(err) {
client.channels.get('CHANNEL ID').send('Error occured: ' + err.message);
}

Related

node.js back-pressure and drain event. I encountered memory leak warning

I am currently studying node.js back-pressure myself.
I intend not to use .pipe() or .pipeline()
because I want to understand back-pressure and drain event.
but I don't know how to write appropriate drain handler.
let's see the below code.
"use strict";
const rs = getReadableStreamSomehow();
const ws = getWritableStreamSomehow();
rs.on("data", function handler(data) {
if (!ws.write(data)) {
ws.once("drain", handler);
}
});
it seems that the above source code has some problem. because I encountered memory leak warning from console.
(node:29788) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 drain listeners added to [WriteStream]. Use emitter.setMaxListeners() to increase limit
Is there anyone knows how to write drain event handler?
Thank you.
I think the following is the right way to handle backpressure and drain event.
const rs = getReadableStreamSomehow();
const ws = getWritableStreamSomehow();
rs.on("data", function (data) {
if (!ws.write(data)) {
rs.pause();
ws.once("drain", function () {
rs.resume();
});
}
});
is it correct?
if it is not correct, please leave a comment.

Handling Mongoose Disconnect

I am using mongoose 4.13.7
I want to connect to mongo but if an error occurs I want to reconnect.
But after 5 reconnects, if an error occurs, the process should exit.
This is the code:
var count = 0;
handleDisconnect();
function handleDisconnect(){
count++;
console.log('Trying to connect to mongo. Attempt : ' + count);
mongoose.connect(config.mongo.uri,{useMongoClient:true});
mongoose.connection.on('error',(error)=>{
if (count >= 5){
console.log('Mongo ERROR');
console.error(error);
process.exit(1);
}
else{
setTimeout(handleDisconnect,1000);
}
});
mongoose.connection.on('open',()=>{
console.log('Connected to mongo at ' + Date.now());
});
}
I have posted the output of the code as well. I don't understand how the attempt count is exceeding 5? There is also a memory leak warning and node:6804 error message. What am I doing wrong?
Output of the code
You attach an event listener for the error event each time the event is emitted. This causes the memory leak warning and also makes the callback function run multiple times per each event ocurrance. You should not add the event handler inside the handleDisconnect() funciton.
Example:
function handleDisconnect(mongoError) {
// check error reason, increment counters, check if errors limit reached
}
mongoose.connection.on('error', handleDisconnect);
You need to check disconnected event when Mongoose lost connection to the MongoDB server. This event may be due to your code explicitly closing the connection, the database server crashing, or network connectivity issues.
mongoose.connection.on('disconnected', () => console.log('Server disconnected from mongoDB'));
error Event: Emitted if an error occurs on a connection, like a parseError due to malformed data or a payload larger than 16MB.
https://mongoosejs.com/docs/connections.html#connection-events

How to find source of memory leak in Node.JS App

I have a memory leak in Node.js/Express app. The app dies after 3-5 days with the following log message:
FATAL ERROR: JS Allocation failed - process out of memory
I setup a server without users connecting, and it still crashes, so I know leak is originating in the following code which runs in the background to sync api changes to the db.
poll(config.refreshInterval)
function poll(refreshRate) {
return apiSync.syncDatabase()
.then(function(){
return wait(refreshRate)
})
.then(function(){
return poll(refreshRate)
})
}
var wait = function wait(time) {
return new Promise(function(resolve){
applog.info('waiting for %s ms..', time)
setTimeout(function(){
resolve(true)
},time)
})
}
What techniques are available for profiling the heap to find the source object(s) of what is taking all the memory?
This takes awhile to crash, so I would need something that logs and I can come back later and analyze.
Is there any option like Java's JVM flag -XX:HeapDumpOnOutOfMemoryError ?
Check out node-memwatch.
It provides a heap diff class:
var hd = new memwatch.HeapDiff();
// your code here ...
var diff = hd.end();
It also has event emitters for leaks:
memwatch.on('leak', function(info) {
// look at info to find out about what might be leaking
});

Node handling Primus socket disconnect during substream write

If I have a (synchronous) process writing to a substream on a socket which disconnects during code execution, what's the best way to keep it from throwing the exception?
(I'm listening to the socket's close/end/etc events to remove the block from flow, but these event handlers wouldn't fire until after the code has finished)
Should I do this:
if (clientStream.stream) {
clientStream.write(bufferData);
} else {
console.log('*** Client FAILURE *****')
}
or use a try/catch?
try {
clientStream.write(bufferData);
} catch (err) {
console.log('*** Client FAILURE *****')
}
I know try/catches are expensive, but I haven't found any info on checking the clientStream.stream object to verify it exists. Maybe it's been deprecated like stream.readyState?

Would EventEmitter cause memory leak if removeAllListeners() is not called?

This question came into my head when I was working with node-imap module. (See https://github.com/mscdex/node-imap)
In this module, the fetch() method would call a callback function that gives it an ImapFetch() object, which your code is suppose to listen on for a 'message' event. The message event in turns passes a message object for each object with events that you need to listen on.
Here's the sample code from the module:
imap.fetch(results,
{ headers: ['from', 'to', 'subject', 'date'],
cb: function(fetch) {
fetch.on('message', function(msg) {
console.log('Saw message no. ' + msg.seqno);
msg.on('headers', function(hdrs) {
console.log('Headers for no. ' + msg.seqno + ': ' + show(hdrs));
});
msg.on('end', function() {
console.log('Finished message no. ' + msg.seqno);
});
});
}
}, function(err) {
if (err) throw err;
console.log('Done fetching all messages!');
imap.logout();
}
);
As shown, the listeners are never removed. This might be fine if the process quits right after it runs once. However, if the process is long running, the code get repeatedly executed, would it cause a memory leak? I.e. since the listeners are never removed, they keep all the fetch and message objects around even though they are only used for the duration of the command.
Is my understanding incorrect?
What happens is that each of your listeners will remain in memory as long as msg remains in memory. This may cause a memory leak if msg lives longer than you intended, by for example still being referenced from somewhere. However, if there are no more references to msg then it will be removed from memory, and the listeners will follow if they have no more references to them either.
You seem to think that the listeners will keep the event emitter around, but it is the other way around.
The example you gave would most likely not cause a memory leak because it looks like msg is disposed by node-imap after it's done with it.

Resources