[stompit STOMP client]Failover not working properly with STOMP producer - javascript

I am using stompit STOMP client. github - https://github.com/gdaws/node-stomp.
I am using ConnectFailover API for reconnect management. I have below code:
var stompit = require('stompit')
var reconnectOptions = {
'maxReconnects': 100,
'randomize' : false
};
var connManager = new stompit.ConnectFailover("failover:(stomp://mqbroker.nyc:61613,stomp://failovermqbroker.nyc:61613)", reconnectOptions);
connManager.on('error', function(error) {
var connectArgs = error.connectArgs;
var address = connectArgs.host + ':' + connectArgs.port;
console.error('Could not connect to ' + address + ' : ' + error.message);
});
connManager.on('connecting', function(connector) {
var address = connector.serverProperties.remoteAddress.transportPath;
console.log('Connecting to ' + address);
});
var totalMsgs = 50;
var count = 0;
var delayMs = 10000;
connManager.connect(function(error, client, reconnect) {
if (error) {
console.log("terminal error, given up reconnecting: " + error);
return;
}
client.on('error', function(error) {
// destroy the current client
client.destroy(error);
// calling reconnect is optional and you may not want to reconnect if the
// same error will be repeated.
reconnect();
});
var sendParams = {
'destination' : '/queue/myqueue',
'persistent' : 'true'
}
function sendMsg (){
setTimeout( function () {
console.log ('sending message ' + (count));
client.send(sendParams).end('Hello number ' + (count));
if (count++ < totalMsgs) {
sendMsg(count);
}
else {
client.send(sendParams).end('DISCONNECT');
client.disconnect();
console.log("Done.");
}
}, delayMs);
}
sendMsg();
});
The problem is that When the client gets disconnected from message broker, The producer keeps executing the sendMsg code and this causes loss of 2-3 messages in between. I want the client to stop executing when in disconnected state and resume when it is connected to failover instance.
Am I using the API incorrectly? What will be correct way to achieve this?
Have hacked at it for some time but this API lacks little documentation on how to use the features. Appreciate all the help.
Thanks,
xabhi

There is no problem with API but the with setTimeout code. I should clear the timeout when the client sees a connection failure.

Related

'RequestDeviceOptions': The provided value cannot be converted to a sequence

I am using a modified version of the sample code for Bluetooth device-information using the Web Bluetooth API.
The Bluetooth device was tested independently using NRF Connect app on my iPhone and everything works as intended. I used the UARTService ID as indicated on the NRF Connect app and used it to set OptionalServices. See the following code snippet.
let UARTService = "6e400001-b5a3-f393-e0a9-e50e24dcca9e"
let UARTCharRX = "6e400002-b5a3-f393-e0a9-e50e24dcca9e"
let UARTCharTX = "6e400003-b5a3-f393-e0a9-e50e24dcca9e"
let options = {};
//options.services = UARTService;
if (document.querySelector('#allDevices').checked) {
options.acceptAllDevices = true;
options.optionalServices = UARTService;
} else {
options.filters = filters;
}
console.log('Requesting Bluetooth Device.........');
console.log('with ' + JSON.stringify(options));
navigator.bluetooth.requestDevice(options)
.then(device => {
console.log('> Name: ' + device.name);
console.log('> Id: ' + device.id);
console.log('> Connected: ' + device.gatt.connected);
return device;
}).then(device => {
return device.gatt.connect();
}).then(function (server) {
console.log("Connected ? " + server.connected);
return server.getPrimaryService(UARTService);
}).then(function (result) {
console.log("DEvice information ", result);
}).catch(error => {
console.log('Argh! ' + error);
});
I get the following error:
Browser is WebBluetoothEnabled
device-info.js:37 Requesting Bluetooth Device.........
device-info.js:38 with {"acceptAllDevices":true,"optionalServices":"6e400001-b5a3-f393-e0a9-e50e24dcca9e"}
device-info.js:57 Argh! TypeError: Failed to execute 'requestDevice' on 'Bluetooth': Failed to read the 'optionalServices' property from 'RequestDeviceOptions': The provided value cannot be converted to a sequence.
Searching for 'RequestDeviceOptions': The provided value cannot be converted to a sequence. on stackoverflow and github issues was without answers.
I suspected a wrong Service UUID but on checking twice revealed it was correct.
optionalServices needs to be a list:
options.optionalServices = [ UARTService ];

Why does JS WebSocket get stuck on CONNECTING in sparkjava?

Here is my websocket code:
#WebSocket
public class SocketServer {
BetterLogger logger = new BetterLogger(Main.logger) {{
loggerName = "socket-server";
}};
public static class ConnectionInit {
String tty;
String device;
}
static class ConnectionOpenResponse {
String tty;
}
#OnWebSocketConnect
public void onConnect(Session user) throws Exception {
Main.logger.info("Websocket connected!");
}
#OnWebSocketClose
public void onClose(Session user, int statusCode, String reason) {
Main.logger.info("Websocket disconnected!");
Main.sessions.closeSession(user);
}
#OnWebSocketMessage
public void onMessage(Session user, String message) {
Main.logger.info("Recevied websock connection: " + message);
try {
if (Main.sessions.contains(user)) {
// treat as raw buffer
Main.sessions.write(user, message);
}
else {
ConnectionInit heartbeat = Main.gson.fromJson(message, ConnectionInit.class);
String s = Main.config.getTTY(heartbeat.device + '.' + heartbeat.tty);
// make sure that the tty exists in config
if (s == null)
user.close(400, "Invalid device/tty!");
// get UUID
Main.sessions.newSession(s, user);
logger.info("created session (" + user + ") with dev " + heartbeat.device + ":" + heartbeat.tty);
user.getRemote().sendString(Main.gson.toJson(new ConnectionOpenResponse() {{
tty = s;
}}, ConnectionOpenResponse.class));
}
}
catch (SessionException e ) {
user.close(500, e.getMessage());
}
catch (JsonSyntaxException e) {
user.close(400, e.getMessage());
}
catch (IOException e) {
// wtf
}
}
}
I have registered it correctly in my Main class, and all seems to work well when I attempt to connect to it using websocat, I can send data and all works well. However, as soon as I create a webpage, the websocket never even opens:
console.log("ws://" + location.hostname + ":" + location.port + "/device");
const socket = new WebSocket("ws://" + location.hostname + ":" + location.port + "/device");
var term = new Terminal();
term.open(document.getElementById('terminal'));
term.write('Press enter to re-flush buffers\n');
//while(socket.readyState !== 1);
//console.log("connected!");
socket.send("testdata");
term.onData( (data) => {
console.log(data);
if (data.charCodeAt(0) == 13)
socket.send('\n');
socket.send(data);
});
// Listen for messages
socket.addEventListener('message', function (event) {
term.write(event.data);
});
Now, the code prints out the correct URL (ws://localhost:16838/device), however, it is stuck at CONNECTING, and throws the following error (which I expect because it's still connecting):
Uncaught DOMException: Failed to execute 'send' on 'WebSocket': Still in CONNECTING state.
Looking at my server logs, I can see that it does print Websocket connected!, which doesn't even make any sense. Any help with fixing why my JS websocket client gets stuck?
Turns out you need to add the open event or else it doesnt actually open

Problem using async functions in NodeJs middleware

I am running into an issue when I try to load the initial data for my blacklist from a Redis DB in my middleware code. Since the DB request takes some time it starts to fail.
Below is my code which gets fired when app starts via app.use(blacklist.blockRequests());.
When I try to make the function async I get the error that new TypeError('app.use() requires a middleware function').
One of the side effects is also that my array is empty when it's called again.
blockRequests: function() {
this.read();
this.logEvent('info', 'There are ' + this.blacklist.length + ' address(es) on the blacklist');
var self = this;
var interceptor = function(request, response, next) {
var ip = request.headers['x-forwarded-for'] || request.connection.remoteAddress;
if (self.isInBlacklist(ip)) {
self.logEvent('warn', 'Rejecting request from ' + ip + ', path and query was ' + request.originalUrl);
response.status(403).send();
} else {
next();
}
}
return interceptor;
},
And here is my read() function code:
read: function() {
try {
// get all records with prefix block:: from redis
redis.redis.keys('block::*', function (err, reply) {
// reply is null when the key is missing
if(err){}
else {
this.blacklist = []
for (let i = 0; i < reply.length; i++) {
let ipInt = reply[i].substring(7)
let ipStr = ipToInt(ipInt).toIP()
this.blacklist.push(ipStr)
}
}
});
} catch (error) {
if (error) {
this.blacklist = [];
}
}
}
If you're trying to make blockRequests() async, then it will start returning a promise and you can't use its return value directly in app.use(). Because then you'd be doing app.use(somePromise) and Express will balk because you have to pass it a function reference, not a promise.
Instead, you will have to use .then() or await to get the return value which is the function which you could then use with app.use().
If you show the larger calling context here (like where you're calling blockRequests() from), then we could offer more ideas on a fuller solution.
Here's a conceptual idea for how you could do this:
blockRequests: function() {
const self = this;
const interceptor = function(request, response, next) {
const ip = request.headers['x-forwarded-for'] || request.connection.remoteAddress;
if (self.isInBlacklist(ip)) {
self.logEvent('warn', 'Rejecting request from ' + ip + ', path and query was ' + request.originalUrl);
response.status(403).send();
} else {
next();
}
}
return interceptor;
},
read: function() {
// get all records with prefix block:: from redis
return new Promise((resolve, reject) => {
redis.redis.keys('block::*', (err, reply) => {
if (err) {
this.blacklist = [];
reject(err);
} else {
this.blacklist = [];
for (let i = 0; i < reply.length; i++) {
let ipInt = reply[i].substring(7)
let ipStr = ipToInt(ipInt).toIP()
this.blacklist.push(ipStr)
}
}
this.logEvent('info', 'There are ' + this.blacklist.length + ' address(es) on the blacklist');
resolve();
});
});
}
// register middleware for using blacklist
app.use(blacklist.blockRequests());
// now read the blacklist and when that is in place, then start the server
blacklist.read().then(() => {
// now we know that blacklist.blacklist is up-to-date
// start your server here
}).catch(err => {
console.log("Unable to start server - error in reading blacklist");
process.exit(1);
});

Long GET requests are repeating in AngularJS & Node App

So I have an AngularJS(1) app which essentially runs a server side script when a user clicks a button.
client side controller Angular calls this method when a button is clicked:
$scope.executeDeployScript = function (demo) {
console.log("Starting "+ demo.instanceName);
$scope.clearDeploymentStatus();
$scope.processStarted = true;
$http.get('/api/demoSelect/startDemo', {
params: {
name: demo.instanceName,
path: demo.scriptPath
}
}).success(function (data) {
if (data === "Done") {
$http.get("/api/demoSelect/startDemo/ip", {
params: {
name: demo.instanceName
}
}).success(function (data) {
demo.url = data.replace(/\s/g, '') + ":" + demo.port
$scope.deploymentStatus = data.replace(/\s/g, '') + ":" + demo.port;
$scope.deploymentSuccess = true;
});
} else {
$scope.deploymentStatus = "Demo deployed failed. Try again : " + data;
$scope.deploymentSuccess = false;
}
});
server side route:
app.get("/api/demoSelect/startDemo", function (req, res, next) {
var child;
var demoName = req.query.name;
var demoPath = req.query.path;
var response = "";
console.log("Running boot script for "+ demoName);
child = exec(demoPath + " " + demoName,
function (error, stdout, stderr) {
if (error !== null) {
console.log('exec error!: ' + stderr);
res.send(stderr);
} else {
console.log(stdout);
res.send("Done");
}
});
});
The script takes a long time to complete (a couple minutes) and I noticed that the GET request is being repeated after a couple of minutes which in turn interrupts the currently running script and starts it again. The repeat is only happening server side since none of the angular client side code is being executed again. I am noticing the get request being repeated in the gulp debug output
Is there some time of time-out value I need to adjust for long get requests to prevent them from being repeated? If so, is that something that's handled in Node or Angular?
Any help is appreciated

Getting Undefined Variable in Javascript

UPDATED CODE: i, I'm new to Javascript programming and getting an undefined variable when trying to assign a new variable from a method.
I'm using node.js and creating a redis server using the redis-client in the "client variable".
var redis = require("redis");
var client = redis.createClient();
client.on("error", function (err) {
console.log("Error " + err); });
var numberPosts;
client.get("global:nextPostId", function(err, replies) {
numberPosts = replies;
console.log(numberPosts);
});
console.log(numberPosts);
When I call console.log inside the call back function it returns the proper value, however when I call the console.log outside of the callback function it returns "undefined". I'm trying to assign the value that is inside the callback function to the global variable numberPosts.
Any help is much appreciated, thanks.
Matt
I believe this will work:
client.get("global:nextPostId", function (err, reply) {
console.log("Number of posts: " + reply.toString());
})
The AJAX call is asynchronous so it doesn't have return value.. instead you have to use callback function and only there you have the value returned by the server method.
Edit: to assign the return value to global variable, first declare global variable:
var _numOfPosts = "";
Then:
client.get("global:nextPostId", function (err, reply) {
_numOfPosts = reply.toString());
})
However, the value won't be available until the AJAX call is finished so your original code can't work. There is not direct return value to store.
You can set timer to some reasonable response time, then have the code using the global variable in there.
Edit II: in order to call the method again once it's finished, have such code:
var _nextPostCallCount = 0;
function GetNextPost() {
//debug
console.log("GetNextPost called already " + _nextPostCallCount + " times");
//sanity check:
if (_nextPostCallCount > 1000) {
console.log("too many times, aborting");
return;
}
//invoke method:
client.get("global:nextPostId", function(err, replies) {
numberPosts = parseInt(replies.toString(), 10);
console.log("num of replies #" + (_nextPostCallCount + 1) + ": " + numberPosts);
//stop condition here.... for example if replies are 0
if (!isNaN(numberPosts) && numberPosts > 0)
GetNextPost();
});
//add to counter:
_nextPostCallCount++;
}
GetNextPost();
This will call the method over and over until the result is 0 or you pass some hard coded limit to prevent endless loop.
Try this instead to see errors:
var redis = require("redis");
client = redis.createClient();
client.on("error", function (err) {
console.log("Error " + err); });
//note the error logging
var numberPosts = client.get("global:nextPostId", function (error, response) {
if (error) {
console.log("async: " + error);
} else {
console.log("programming: " + response);
}
});
console.log("is lotsa fun: " + numberPosts);
As Shadow Wizard has pointed out you are trying to use numberPosts before there is something in it, as client.get() hasn't returned anything.
Read this to get a handle on node.js flow:
http://www.scribd.com/doc/40366684/Nodejs-Controlling-Flow
I was facing the the same issue when I applied the MVC framework.
To solve the problem, I employed the render function.
In the posts Model
exports.get = function(id,render) {
client.incr('post:id:'+id, function(err, reply) {
render(reply);
});
};
In the posts Controller
exports.get = function(req, res) {
posts.get('001', function (data){res.render('index',{post:data});});
};

Categories