Creating new processes using node js does not have pid - javascript

I am following the example presented here
to create a server that would run on multiple cores.I get the following error:
created worker: undefined
created worker: undefined
created worker: undefined
created worker: undefined
workers[m.process].lastCb=new Date().getTime();
^
TypeError: Cannot set property 'lastCb' of undefined
at Worker.<anonymous> (/home/anr/Desktop/node js/clustering2.js:56:29)
at Worker.EventEmitter.emit (events.js:98:17)
at ChildProcess.EventEmitter.emit (events.js:98:17)
at handleMessage (child_process.js:318:10)
at Pipe.channel.onread (child_process.js:345:11)
This is my code:
var cluster=require('cluster');
var os=require('os');
var http=require('http');
var numCores=os.cpus().length;
var rsswarn=(50*1024*1024),
heapWarn=(50*1024*1024);
var workers={};
if(cluster.isMaster)
{
for(var i=0;i<numCores;i+=1)
{
createWorker();
}
setInterval(function killWorkers(){
var time=new Date().getTime();
for(pid in workers)
{
if(workers.hasOwnProperty(pid) && workers[pid].lastCb+5000<time)
{
console.log('Long running process '+pid+ ' killed');
workers[pid].worker.kill();
delete workers[pid];
createWorker();
}
}
},1000);
}
else
{
http.Server(function makeServer(req,res){
if (Math.floor(Math.random() * 200) === 4) {
console.log('Stopped ' + process.pid + ' from ever finishing');
while(true) { continue; }
}
res.writeHead(200);
res.end('hello world from ' + process.pid + '\n');
}).listen(8000);
//Report stats once a second
setInterval(function report(){
process.send({cmd: "reportMem", memory: process.memoryUsage(), process: process.pid});
}, 1000);
}
function createWorker()
{
var worker=cluster.fork();
console.log('created worker: '+worker.pid);
workers[worker.pid]={worker:worker,lastCb:(new Date().getTime()-1000)};
worker.on('message',function(m){
if(m.cmd==='reportMem')
{
workers[m.process].lastCb=new Date().getTime();
if(m.memory.rss>rssWarn)
{
console.log('worker thread '+m.process+' taking too much memory');
}
}
});
}

You will find the pid in worker.process.pid. Either the example has a typo, or this has changed for newer versions of node.js.
// This works:
console.log('created worker: ' + worker.process.pid);
Reference: worker.process and ChildProcess.pid
After changing all worker.pid to worker.process.pid you will also notice there is a typo with the variable rsswarn which is later called as rssWarn
After fixing these two things, your code should work.
Have fun!

Related

Node.js broadcasting twice

I'm giving my first steps with node.js. I'm trying to implement a simple chat room to get the basics, but can't figure out why after every broadcast, a second (empty) message is automatically sent. This behaviour happens most of the time but not always. I'm using Netbeans in Windows, with Putty to simulate the client connections.
Console output:
Server running
::1:60616 joined
::1:60617 joined
-----------
Broadcasting:
hello
-----------
Broadcasting:
-----------
Broadcasting:
goodbye
-----------
Broadcasting:
-----------
Client 1:
Hi ::1:60616!
hello
goodbye
Client 2:
Hi ::1:60617!
::1:60616 says hello::1:60616 says
::1:60616 says goodbye::1:60616 says
Code
var net = require('net');
var chatServer = net.createServer();
var clientList = [];
console.log('Server running');
chatServer.on('connection', function (client) {
client.name = client.remoteAddress + ':' + client.remotePort;
client.write('Hi ' + client.name + '!\n');
console.log(client.name + ' joined');
clientList.push(client);
client.on('data', function (data) {
console.log('Broadcasting: ');
console.log(data.toString());
console.log('-----------');
broadcast(data, client);
});
client.on('end', function () {
console.log(client.name + ' quit');
clientList.splice(clientList.indexOf(client), 1);
});
client.on('error', function (e) {
console.log(e);
});
});
function broadcast(message, sender) {
var text = sender.name + " says " + message;
var cleanup = [];
clientList.forEach(function (client) {
if (client !== sender) {
if (client.writable) {
client.write(text);
} else {
cleanup.push(client);
client.destroy();
}
}
});
cleanup.forEach(function (client) {
clientList.splice(clientList.indexOf(client), 1);
});
}
chatServer.listen(9000);
You can't rely on the raw data event to present you with "well-rounded" chunks of data. It may come in pieces, and you can't necessarily control how large those pieces are, or that they get split on particular boundaries.
However, there are modules that can help you, for instance split, which will split the data into separate (full) lines:
const split = require('split');
...
client.pipe(split()).on('data', function (data) {
// `data` is now a separate line
console.log('Broadcasting: ');
console.log(data.toString());
console.log('-----------');
broadcast(data, client);
});

No output from jasmine-node on FilesizeWatcherSpec - Newbie Alert

I'm new to Node.js and jasmine, and my JavaScript experience is old and rusty, so I'm a newbie there too. I finished Manuel Kiessling's book, The Node Beginner Book, and I am working my way through his second book, The Node Craftsman Book. I'm stuck on the FilesizeWatcher tutorial. I've been able to run earlier tests but this one is not working. There is a similar question on SO: No output from jasmine-node but the answer isn't working for me.
I'll post my code here and hopefully somebody can tell me what I'm doing wrong.
FilesizeWatcherSpec.js:
'use strict';
var FilesizeWatcher = require('./FilesizeWatcher');
var exec = require('child_process').exec;
describe('FilesizeWatcher', function() {
var watcher;
afterEach(function() {
watcher.stop();
});
it('should fire a "grew" event when the file grew in size', function(done) {
var path = './var/tmp/filesizewatcher.test';
exec('rm -f ' + path + ' ; touch ' + path, function() {
watcher = new FilesizeWatcher(path);
watcher.on('grew', function(gain) {
expect(gain).toBe(5);
done();
});
exec('echo "test" > ' + path, function(){});
});
});
it('should fire a "shrank" event when the file shrank in size', function(done) {
var path = './var/tmp/filesizewatcher.test';
exec('rm -f ' + path + ' ; echo "test" > ' + path, function() {
watcher = new FilesizeWather(path);
watcher.on('shrank', function(loss) {
expect(loss).toBe(3);
done();
});
exec('echo "a" > ' + path, function(){});
});
});
it('should fire an "error" if path does not start', function(done) {
var path = 'var/tmp/filesizewatcher.test';
watcher = new FilesizeWather(path);
watcher.on('error', function(err) {
expect(err).toBe('Path does not start with a slash');
done();
});
});
});
FilesizeWatcher.js:
'use strict';
var fs = require('fs');
var util = require('util');
var EventEmitter = require('events').EventEmitter;
var FilesizeWatcher = function (path) {
var self = this;
if (/^\//.test(path) === false) {
process.nextTick(function() {
self.emit('error', 'Path does not start with a slash');
});
return;
}
fs.stat(path, function (err, stats) {
console.log('stats= ' + stats);
self.lastfilesize = stats.size;
});
self.interval = setInterval(
function () {
console.log('We are in function()');
fs.stat(path, function (err, stats) {
if (stats.size > self.lastfilesize) {
self.emit('grew', stats.size - self.lastfilesize);
self.lastfilesize = stats.size;
}
if (stats.size < self.lastfilesize) {
self.emit('shrank', self.lastfilesize - stats.size);
self.lastfilesize = stats.size;
}
}, 1000);
});
};
util.inherits(FilesizeWatcher, EventEmitter);
FilesizeWatcher.prototype.stop = function () {
clearInterval(this.interval);
};
module.exports = FilesizeWatcher;
Console output:
C:\Users\pdl\Projects\NodeCraftsman>jasmine-node ./FilesizeWatcherSpec.js
C:\Users\pdl\Projects\NodeCraftsman>
Other tests run fine:
C:\Users\pdl\Projects\NodeCraftsmanTestDrivenDevelopment>jasmine-node spec\greetSpec.js
..
Finished in 0.006 seconds
2 tests, 2 assertions, 0 failures, 0 skipped
C:\Users\pdl\Projects\NodeCraftsmanTestDrivenDevelopment>
I added --captureExceptions to see if I could get any information and I got the TypeError: self.callbacks.error is not a function.
My first problem was as Eppilo suggested below, that I needed to use process.nextTick on self.callbacks'error'. Mixing async code with sync code causes the error event to be fired before the error handler is registered. So I made the changes and am now using the EventEmitter but I'm still getting the following errors:
If I include the "." in the path: var path = './var/tmp/filesizewatcher.test'; then the file gets written. Otherwise, it does not.
If the file does NOT get written, stats= undefined and I receive this error:
TypeError: Cannot read property 'size' of undefined
at C:\Users\pdl\Projects\NodeCraftsman\FilesizeWatcher.js:19:34
at FSReqWrap.oncomplete (fs.js:82:15)
If the file DOES get written, then I receive this error:
Error: Uncaught, unspecified "error" event. (Path does not start with a slash)
at emit (events.js:144:17)
at C:\Users\pdl\Projects\NodeCraftsman\FilesizeWatcher.js:12:18
at nextTickCallbackWith0Args (node.js:419:9)
at process._tickCallback (node.js:348:13)
Of course, it's not supposed to start with a slash. That is the test. But when I remove the --captureExceptions from the command, I still get no output.
First of all try and run Jasmine on verbose mode and capture exceptions:
jasmine-node ./FilesizeWatcherSpec.js --verbose --captureExceptions
Link: https://github.com/mhevery/jasmine-node/wiki/Command-Line-Usage
Also try to make the error checking asynchronous:
if (/^\//.test(path) === false) {
process.nextTick(function() {
self.callbacks['error']('Path does not start with a slash');
});
return;
}
Newbie as well, with not enough reputation to comment.
I got the same no output on my Mac too, and was able to get the test to work with this.
There is an error in FilesizeWatcher.js.
Currently:
self.interval = setInterval(
function (){
...
fs.stat(path, function (err, stats) {
...
}, 1000);
});
It should instead be:
self.interval = setInterval(
function (){
...
fs.stat(path, function (err, stats) {
...
});
},1000);
Just sharing my findings, cheers.

Nodejs server stop accept connections after a few hours

I made an application to the control of simultaneous logins, in starts everything works perfectly, however after a few hours i can not longer connect to the server, my client returns me the following error: net :: ERR_CONNECTION_TIMED_OUT and on the server side does not happen any error like it was running correctly... code below:
CLIENT SIDE:
var socket;
function connect(id) {
socket = io.connect('http://IP:4200');
socket.on('connect', function (data) {
socket.emit('join', id);
});
socket.on('messages', function (data) {
console.log('MSG: ' + data.toString());
switch (data.toString()) {
case "kick":
socket.close();
console.log("KICK!");
break;
case "duplicate_entry":
socket.close();
console.log("Another user connection!");
break;
}
});
}
SERVER SIDE:
var express = require('express');
var app = express();
var server = require('http').createServer(app);
var io = require('socket.io')(server);
var clients = [];
app.use(express.static(__dirname + '/bower_components'));
function logtimestamp() {
var log_date = new Date();
log_date = '[' + log_date.getFullYear() + '/' + (log_date.getMonth() + 1) + '/' + log_date.getDate() + ' ' + log_date.getHours() + ':' + log_date.getMinutes() + ':' + log_date.getSeconds() + ']';
return log_date;
}// FUNCTION logtimestamp
console.log("Start time: " + logtimestamp());
console.log("Server port 4200")
console.log("websocket server created!");
try {
io.on('connection', function (client) {
try {
var id;
var conexao;
client.on('join', function (data) {
try {
console.log('Client connected...'+logtimestamp()+' ID:' + data);
id = data;
conexao = {
ws: client,
id_user: data
};
clients.push(conexao);
for (var x = 0; x < clients.length; x++) {
//desconect previous user
try {
if (clients[x].id_user == id) {
if (clients[x].ws != conexao.ws) {
clients[x].ws.emit('messages', 'duplicate_entry');
clients.splice(x, 1);
}
}
} catch (err) {
console.log("ERROR 1: " + err.message);
}
}
} catch (err) {
console.log("ERROR 2: " + err.message);
}
});
} catch (err) {
console.log("ERROR 3: " + err.message);
}
});
} catch (err) {
console.log("ERROR 4: " + err.message);
}
server.listen(4200);
I see a couple possible issues. It is hard for us to know by just inspecting code which issues actually are the cause of your issue. In any case, you should clean up these issues and see if it improves the situation:
You should respond the the disconnect event and immediately remove any socket from your clients array when it disconnects.
In your loop where you are looking to removing any prior instances of a given user, your for loop will not work properly when you are doing .splice(x, 1) in the middle of the for loop. This will move all items after it does one in the array causing you to skip the comparison of the next element in the array. One simple way to get around this is to iterate the array backwards: for (var x = clients.length - 1; x >= 0; x--) because then the elements who's position are affected after the .splice() are elements you have already looked at. None will be missed.
Beyond this, you should examine the memory usage of the nodejs process, the open sockets by the nodejs process and the CPU usage of the nodejs process to see if any of those point to any possible issues.
And, what is your deployment environment? Is there a proxy server in front of your web server?

Access worker environment from master (Node.js Cluster)

I fork workers in my Node.js application via the Cluster module and pass a custom ID to the environment of all my workers. That works well for far.
However, I do not know how I can access this id in my master when an 'online' or 'exit' event is emitted.
The documentation is not very helpful. Could you please point me the right way?
var cluster = require('cluster');
if (cluster.isMaster) {
//MASTER
function fork() {
var worker_env = {worker_id:'my_custom_id'};
cluster.fork(worker_env);
}
cluster.on('online', function(worker) {
console.log(worker.process.env.worker_id); // undefined
//
// How can I access my custom worker id here?
//
});
cluster.on('exit', function(worker, code, signal) {
//
// And here...?
//
fork();
});
} else {
// WORKER
console.log(process.env.worker_id); // my_custom_id
}
theres no way, the worker process env is not exposed to the master.
One aproach can be a map of our cluster (a object containig the needed info).
Something like these:
var cluster = require('cluster');
if (true === cluster.isMaster) {
//CODE EXECUTED BY MASTER
var cluster_map = {}; // Here we store the workers info in a object
var restart_Limit = 10; // max global worker restart (10)
function fork_worker(myWorkerId) {
// these makes worker_id available in the worker
var worker = cluster.fork({
worker_id: myWorkerId
});
// max restarts limit (global)
if (worker.id >= restart_Limit) {
console.log('Restart limit reached, bye!');
process.kill();
}
// here we add the key "myWorkerId" to the cluster map
cluster_map[worker.id] = myWorkerId;
// WORKER AUTO-KILL
setTimeout(function() {
console.log('stoping...' + myWorkerId);
worker.kill();
}, 3000);
}
cluster.on('online', function(worker) {
var online_proc = cluster_map[worker.id];
console.log('worker online: ' + online_proc + '\n Restarts: ' + worker.id);
});
cluster.on('exit', function(worker, code, signal) {
var exited_proc = cluster_map[worker.id];
// delete the process from the cluster map
delete cluster_map[worker.id];
console.log("worker offline: " + exited_proc);
// WORKER AUTO-RESTART
setTimeout(function() {
console.log('Restarting... ' + exited_proc);
fork_worker(exited_proc);
}, 3000);
});
// start the magic ( 3 workers )
(function() {
fork_worker('id_1');
fork_worker('id_2');
fork_worker('id_3');
})();
} else {
//CODE EXECUTED BY EACH WORKER (process env is present here).
console.log('hi from the worker, process.env: ' + process.env.worker_id);
// all the hard work for the workers here.
}

Javascript can't find these variables, why?

I'm using Phonegap to create an Android application (Voice Recorder), but I had these 2 errors in my code:
ReferenceError: Can't find variable: Media.
TypeError: Result of expression 'mediaRec' undefined is not an object.
The first error happens when the application runs. The second error happens when I call the recordAudio(); method.
Tell me what's the problem please if you know.
var mediaRec;
var src;
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
}
function init() {
document.getElementById('status').innerHTML = "Recording Status";
src = "myrecording.mp3";
mediaRec = new Media(src, onSuccess, onError);
}
function recordAudio() {
// Record audio
mediaRec.startRecord();
// Stop recording after 10 sec
var recTime = 0;
var recInterval = setInterval(function() {
recTime = recTime + 1;
setAudioPosition(recTime + " sec");
if (recTime >= 10) {
clearInterval(recInterval);
}
}, 1000);
}
// Stop audio
function stopRecording() {
if (mediaRec) {
mediaRec.stopRecord();
}
clearInterval(mediaTimer);
mediaTimer = null;
}
// onSuccess Callback
function onSuccess() {
console.log("recordAudio():Audio Success");
}
// onError Callback
function onError(error) {
alert('code: ' + error.code + '\n' + 'message: ' + error.message + '\n');
}
// Set audio position
function setAudioPosition(position) {
document.getElementById('rec_position').innerHTML = position;
}
Thanks.
I think scr = "/android_asset/www/myrecording.mp3" because directory phonegap in asset/www/...
If directory not found javascript in phonegap show alert like that ReferenceError: Can't find variable: Media.
Be sure to add the 'cordova-plugin-media' plugin which defines a global Media constructor. See Cordova media documentation
cordova plugin add cordova-plugin-media --save
The other reason this might happen is be sure to wait until device is ready Cordova event before new Media constructor is called.

Categories