simulate multiple socket.io connection - node.js

Not a duplicate of : this question, as I'm trying to use the link posted as answer to solve my problem.
I'm creating a little dummy socket client to help testing one of my product, it looks like so :
var ee = require('events').EventEmitter;
require('http').globalAgent.maxSockets = 1000;
function Dummy(){
this.config = require('../config/credentials.js');
this.socket = require('socket.io-client')(this.config.socketIO.url);
var self = this;
this.socket.on('task', function(task) {
self.createTask(task);
});
}
util.inherits(Dummy, ee);
module.exports = Dummy;
Dummy.prototype.createTask = function(name){
var self = this;
setInterval(function sendStuff(){
self.socket.emit("msg")
}, 1000);
};
On its own, it works fine; However, when I try to launch many of them like so :
for (var i = 0; i < 100; i++) {
fakeClients.push(new Dummy());
};
Is appears to pool connections and shows as one client only.
Based on this link, I thought that by using socket.io-client, I'd avoid the pooling behaviour, yet it doesn't work. Am I doing something wrong?
I've simplified the loop btw, I actually make sure there's a delay between creations to avoid sync heartbeats.
Ideas?

Found the answer, it goes like this :
function Dummy(){
this.config = require('../config/credentials.js');
this.socket = require('socket.io-client').connect(this.config.socketIO.url, { "force new connection": true });
var self = this;
this.socket.on('task', function(task) {
self.createTask(task);
});
}
By using the connect() function, we can set the force new connection flag to true and avoid the pooling. Simple!

Related

How to translate Kafka pub-sub semantics into a peakNext promise semantics for unittesting in NodeJS

While unittesting my NodeJS application I'm trying to create a simple helper class that will translate the Kafka pub-sub semantics into a simpler API suited for unittesting.
My idea is to be able to write mocha unittest like this:
const testSubscriber = kafkaTestHelper.getTestSubscriber({topic:'test'});
return someKafkaProducer.sendAsync({topic: 'test', message: randomWord})
.then(() =>
testSubscriber.next()
).then(msg => {
msg.should.equal(randomWord);
});
Of course I would also add helper methods such as
testSubscriber.nextUntil(someFilter)
This is inspired by the AKKA.NET TestKit which has a similar approach.
I have two questions:
Is this a reasonable approach or is there some cleaner way to unittest application logic based on Kafka stream processing in NodeJS?
Can anybody post coding examples showing how to make testSubscriber work as I intend?
This might not be the most elegant solution but it seems to work, at least for my initial testing. The trick is to create an ever growing list of Promises for which the resolver function is kept by reference in an array called 'resolvers'. Then when a message comes in, the resolver is invoked with the message. In this way I can return promises to any unittest invoking next() and it will work transparently if either the message was already delivered or it will be delivered in the future.
I still feel I'm reinventing the wheel here, so any comments would still be greatly appreciated.
function TestSubscriber(consumer, initialMessageFilter) {
this.consumer = consumer;
let promiseBuffer = [];
let resolvers = [];
let resolveCounter = 0;
let isStarted = false;
const ensurePromiseBuffer = function() {
if (promiseBuffer.length === 0 || resolveCounter >= resolvers.length) {
const newPromise = new Promise(function(resolve, reject) {
resolvers.push(resolve);
});
promiseBuffer.push(newPromise);
}
}
const that = this;
this.consumer.on('message', function(message) {
if (!isStarted) {
//Determine if we should start now.
isStarted = initialMessageFilter === undefined || initialMessageFilter(message);
}
if (isStarted) {
ensurePromiseBuffer();
const resolver = resolvers[resolveCounter];
resolver(message);
resolveCounter++;
that.consumer.commit(function(err, data) {
if (err) {
//Just log any errors here as we are running inside a unittest
log.warn(err)
}
})
}
});
this.next = function() {
ensurePromiseBuffer();
return promiseBuffer.shift();
};
}
const cache = {};
module.exports = {
getTestSubscriber: function({topic}, initialMessageFilter) {
if (!cache[topic]) {
const consumer = kafka.getConsumer({topic, groupId: GROUP_ID});
cache[topic] = new TestSubscriber(consumer, initialMessageFilter);
}
return cache[topic];
}
}

Node.js EventEmitter - bad things are happening

I've been trying to resolve a bug in a nodejs application, and have narrowed it down to the way I've implemented event emitters. The application is an express.js app, has uses classes. There's some critical aspect of NodeJS that I must be missing, around memory usage and class / object lifecycles. I was hoping someone could point out why what I'm doing is not working as expected.
Here's the code:
// ServiceWrapper.js:
var events = require('events');
var ServiceClient = function(opts) {
this.foobar = "";
this.opts = opts;
this.hasFoo = false, this.hasBar = false;
}
ServiceClient.prototype = new events.EventEmitter();
ServiceClient.prototype.getFoo = function() {
var self = this;
self.hasFoo = true;
self.foobar += "foo";
self.emit('done','foo');
}
ServiceClient.prototype.getBar = function() {
var self = this;
self.hasBar = true;
self.foobar += "bar";
self.emit('done','bar');
}
var ServiceWrapper = function(){}
ServiceWrapper.prototype.getResponse = function(options, callback) {
var servClient = new ServiceClient({});
servClient.on('done', function(what) {
if (servClient.hasFoo && servClient.hasBar) {
console.log("foo && bar")
callback(servClient.foobar);
}
else {
console.log("Don't have everything: " + servClient.foobar);
}
});
servClient.getFoo();
servClient.getBar();
}
module.exports = ServiceWrapper
And then in my express app:
var ServiceWrapper = require('ServiceWrapper');
app.get('/serviceReponse', function(req,res) {
var servWrapper = new ServiceWrapper();
servWrapper.getResponse(function(ret) {
res.end(ret);
});
});
The behaviour on the web app works as expected: response is set to "foobar". However, looking at the logs, it looks like there's a memory leak - multiple instances of servWrapper. After starting the application, the first request generates:
Don't have everything: foo
foo && bar
However, if I refresh the page, I see this:
foo && bar
Don't have everything: foo
foo && bar
foo && bar
And with every refresh, the listener detects multiple 'done' events - foo && bar outputs keeps growing (assuming there's more and more instances of ServiceWrapper that persist in memory).
Why does this happen? (I expect to see the output that I get on the first request from every request).
Thanks to the guys on #node.js on freenode for assisting with this:
sure, but every time you attach listeners, you're attaching them to the same emitter
since you didn't localize the prototype's state to your instance, the prototype methods act upon the state of the prototype object.
I believe you can fix it by simply doing EventEmitter.call(this) in the constructor
See the following link for more info:
http://nodejs.org/api/util.html#util_util_inherits_constructor_superconstructor

I am trying to open 10 websocket connections with nodejs, but somehow my loop doesnt work

var WebSocket = require('ws')
var ws = [];
for (var i = 0; i < 10 ; ++i) {
ws[i] = new WebSocket('ws://127.0.0.1:9898/echo/websocket');
ws[i].on('open', function() {
ws[i].send('why');
});
}
I am trying to open 10 websocket connections with nodejs, but somehow my loop doesnt work. What is wrong with my code? Thanks
As Nitzan Shaked says your issue is due to the loop problem. When the callbacks start to fire all the i values are 9 here.
generic solution
As a generic solution, solve it using a simple closure.
var WebSocket = require('ws')
var ws = [];
for (var i = 0; i < 10 ; ++i) {
ws[i] = new WebSocket('ws://127.0.0.1:9898/echo/websocket');
ws[i].on('open', generator(ws[i]));
}
//generator makes a function with present object and returns it
var generator = function (k) {
return function() {
k.send('why');
}
}
easy way
But the easiest way specific to your context would be by simply replacing ws[i] by a this
var WebSocket = require('ws')
var ws = [];
for (var i = 0; i < 10 ; ++i) {
ws[i] = new WebSocket('ws://127.0.0.1:9898/echo/websocket');
ws[i].on('open', function() {
this.send('why');
});
}
Classic Javascript loop gotcha. Look here: Javascript infamous Loop issue?.
Basically at the point where the callback is called, ws[i].send(...), i refers to i at the end of the loop, not where you are defining the callback.
EDIT -- as Casey Chu noted, I have a silly bug in my code example. Instead of fixing it and coming up with a duplicate of other answers, I refer you to the (currently) 2 other answers which are perfectly working.

node.js recursive setTimeout() inside of a psuedoclass

I think I'm having a difficult time wrapping my head around the scope of the following code:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
this.time = time;
this.tick = function() {
this.emit('tick');
setTimeout(this.tick(), this.time);
};
}
util.inherits(Ticker, EventEmitter);
var newTicker = new Ticker(1000);
newTicker.on('tick', function() { console.log("TICK"); });
newTicker.tick();
What ends up happening, is that the "tick" gets called many, many times filling up the stack without the setTimeout actually setting the timeout to one second.
Could any explain to me what's going on?
EDIT: I looked a little bit more, and I still couldn't figure out the issue of scope, really.
What I ended up doing was following the solution that was given for the problem, which I tried to solve by way of setTimeout().
The solution given was:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
var self = this;
this.time = time;
setInterval(function() {
self.emit('tick');
}, self.time);
};
util.inherits(Ticker, EventEmitter);
var ticker = new Ticker(1000);
ticker.on('tick', function() { console.log("TICK"); });
It does make more sense to me... What I'm wondering now is: Do inner functions and objects in javascript not keep track of their parent's scope and variables?
Your initial problem is that you were calling this.tick inside your setTimeout:
setTimeout(this.tick(), this.time);
Instead, you want to pass a reference to the this.tick function:
setTimeout(this.tick, this.time);
This fixes the problem for the first loop, but the second call to tick (which comes from the setTimeout) is not bound to the correct scope; so, you can bind the function reference to the current value of this using bind:
setTimeout(this.tick.bind(this), this.time);
(You can also use the self trick if you prefer.)
So, the full working program is:
var EventEmitter = require('events').EventEmitter, util = require('util');
// Here is the Ticker constructor:
var Ticker = function(time) {
this.time = time;
this.tick = function() {
this.emit('tick');
setTimeout(this.tick.bind(this), this.time);
};
}
util.inherits(Ticker, EventEmitter);
var newTicker = new Ticker(1000);
newTicker.on('tick', function() { console.log("TICK"); });
newTicker.tick();

http.Clientrequest.abort() ends program

I'm having some issues using Node.js as a http client against an existing long polling server. I'm using 'http' and 'events' as requires.
I've created a wrapper object that contains the logic for handling the http.clientrequest. Here's a simplified version of the code. It works exactly as expected. When I call EndMe it aborts the request as anticipated.
var http = require('http');
var events = require('events');
function lpTest(urlHost,urlPath){
this.options = {
host: urlHost,
port: 80,
path: urlPath,
method: 'GET'
};
var req = {};
events.EventEmitter.call(this);
}
lpTest.super_ = events.EventEmitter;
lpTest.prototype = Object.create(events.EventEmitter.prototype, {
constructor: {
value: lpTest,
enumerable: false
}
});
lpTest.prototype.getData = function getData(){
this.req = http.request(this.options, function(res){
var httpData = "";
res.on('data', function(chunk){
httpData += chunk;
});
res.on('end', function(){
this.emit('res_complete', httpData);
}
};
}
lpTest.prototype.EndMe = function EndMe(){
this.req.abort();
}
module.exports = lpTest;
Now I want to create a bunch of these objects and use them to long poll a bunch of URL's. So I create an object to contain them all, generate each object individually, initiate it, then store it in my containing object. This works a treat, all of the stored long-polling objects fire events and return the data as expected.
var lpObject = require('./lpTest.js');
var objWatchers = {};
function DoSomething(hostURL, hostPath){
var tempLP = new lpObject(hostURL,hostPath);
tempLP.on('res_complete', function(httpData){
console.log(httpData);
this.getData();
});
objWatchers[hosturl + hostPath] = tempLP;
}
DoSomething('firsturl.com','firstpath');
DoSomething('secondurl.com','secondpath);
objWatchers['firsturl.com' + 'firstpath'].getData();
objWatchers['secondurl.com' + 'secondpath'].getData();
Now here's where it fails... I want to be able to stop a long-polling object while leaving the rest going. So naturally I try adding:
objWatchers['firsturl.com' + 'firstpath'].EndMe();
But this causes the entire node execution to cease and return me to the command line. All of the remaining long-polling objects, that are happily doing what they're supposed to do, suddenly stop.
Any ideas?
Could it have something to do with the fact that you are only calling getData() when the data is being returned?
Fixed code:
function DoSomething(hostURL, hostPath){
var tempLP = new lpObject(hostURL,hostPath);
tempLP.on('res_complete', function(httpData){
console.log(httpData);
});
tempLP.getData();
objWatchers[hosturl + hostPath] = tempLP;
}
I have seemingly solved this, although I'm note entirely happy with how it works:
var timeout = setTimeout(function(){
objWatchers['firsturl.com' + 'firstpath'].EndMe();
}, 100);
By calling the closing function on the object after a delay I seem to be able to preserve the program execution. Not exactly ideal, but I'll take it! If anyone can offer a better method please feel free to let me know :)

Resources