Updating Meteor collection on asynch callback - meteor

I have a meteor app that uses the node module MQTTClient.
This client sends events whenever something is published to a topic that the client subscribes too.
When the event happens I'd like to update an entry in a collection, but when I do this I get assertion failures and the DB gets corrupted.
Assertion failed: (handle->InternalFieldCount() > 0), function Unwrap, file ../src/node_object_wrap.h, line 61.
Exited from signal: SIGABRT
Your application is crashing. Waiting for file change.
This is what I currently have:
...
client.connect(function () {
console.log('connected to MQTT broker');
Fiber(function(){
var allTopics = Topics.find({});
allTopics.forEach(function(topic){
console.log('subscribing to ' + topic.name);
client.subscribe(topic.name);
});
}).run();
});
var onPublish = function(topicName, payload, message_id) {
console.log("New message: " + topicName + ":" + payload);
Topics.insert({name: payload, value: payload});
};
var wrappedOnPublish = Meteor.bindEnvironment(onPublish, function(e){
var message = "Something went wrong! " +
"Everything is broken! " +
"Your life is ruined!";
console.log(message, e.stack);
});
client.on('publish', wrappedOnPublish);
I have also tried to handle the callback by wrapping it in a Fiber(..).run() but the exact same error occur.

Related

Add new Subscription to Rocket chat

I want to create a new subscription e.g (stream-all-messages) in Rocket Chat same as stream-room-messages which is already present in docs.
I am using DDP listener to test it, following are the examples which I am trying.
// Subscribe to a message stream from a channel or group
console.log("Attempting to subscribe to the Group/Channel now.\n");
ddpClient.subscribe("stream-room-messages", [RoomId, false], function() {
console.log(ddpClient.collections);
console.log("Subscription Complete.\n");
// Display the stream on console so we can see its working
console.log("\nStarting live-stream of messages.:\n");
ddpClient.on("message", function(msg) {
console.log("Subscription Msg: " + msg);
});
});
above example works because stream-room-messages already present but when I try to execute the following it raises an error i.e.
Subscription Msg: {"msg":"nosub","id":"2","error":{"isClientSafe":true,"error":404,"reason":"Subscription 'stream-only-messages' not found","message":"Subscription 'stream-all-messages' not found [404]","errorType":"Meteor.Error"}}
when I call this
// Subscribe to a message stream from a channel or group
console.log("Attempting to subscribe to the Group/Channel now.\n");
ddpClient.subscribe("stream-all-messages", [RoomId, false], function() {
console.log(ddpClient.collections);
console.log("Subscription Complete.\n");
// Display the stream on console so we can see its working
console.log("\nStarting live-stream of messages.:\n");
ddpClient.on("message", function(msg) {
console.log("Subscription Msg: " + msg);
});
});
Please help me out how can I add a new subscription.

Calling Meteor Method from within Particle Photon Stream of Promises produces error: Error("Meteor code must always run within a Fiber. "

I'm connecting to Particle.io event stream and trying to call a Meteor Method with the event name and event data from the stream as arguments.
var Particle = Meteor.npmRequire('particle-api-js');
var particle = new Particle();
var particleLogin = particle.login({
username: Meteor.settings.particle_username,
password: Meteor.settings.particle_password
});
particleLogin.then(
function(data) {
var token = data.body.access_token;
console.log(token);
var eventStream = particle.getEventStream({
deviceId: Meteor.settings.PhotonName,
auth: token
});
eventStream.then(function(stream) {
stream.on('event', function(data) {
console.log(data.name + ": " + data.data);
Meteor.call('newStreamData', data.name, data.data); // Produces aforementioned error
});
});
}
)
I've tried including the call from inside of a Meteor.bindEnvironment block and nothing happens.
stream.on('event', Meteor.bindEnvironment(function(data) {
console.log(data.name + ": " + data.data); // Never gets called
Meteor.call('newStreamData', data.name, data.data); // Never gets called
}));

'end' undefined for this.response in Iron Router for Meteor

I have created an HTTP POST endpoint for my Meteor server using Iron Router. I would like to send a response back to the requestor with a JSON of the status and some other metadata.
Here is the code for the endpoint:
Router.route('/new_video', {where: 'server'})
.post(function(){
var body = this.request.body;
this.response.setHeader('Content-Type', 'application/json');
var filename = body.filename;
console.log('New video uploaded for: ' + filename);
Meteor.call('newUpload', filename, function(error, results){
if (error){
throw new Meteor.Error("new-video-upload-failed", "New video could not be uploaded.");
var message = {
url: '/new_video',
status: 'success'
};
}
else{
var videoId = results;
console.log('Returned video id: ' + videoId);
var message = {
url: '/new_video',
status: 'failure'
};
}
this.response.end(JSON.stringify(message));
});
});
The Meteor console is printing:
=> Meteor server restarted
I20151002-15:51:26.311(-4)? New recording for: 1422776235,43.46756387,-80.54130886.mp4
I20151002-15:51:26.515(-4)? Returned video id: QiHXxZSb2sn9aNRPs
I20151002-15:51:26.569(-4)? Exception in delivering result of invoking 'newRecording': TypeError: Cannot call method 'end' of undefined
I20151002-15:51:26.569(-4)? at shared/routes.js:79:17
It's a common pitfall of JS where the value of this is modified due to the introduction of another function callback in the Meteor.call.
If you're using Meteor 1.2 which comes with ES2015 arrow functions you can solve the issue using this function declaration syntax instead :
Meteor.call('newUpload', filename, (error, results) => {
// here 'this' will keep referencing the POST route context
// so you can safely use this.response
});
If you're not using Meteor 1.2, use this syntax instead :
Meteor.call('newUpload', filename, function(error, results) {
// inner function is bound to parent function 'this'
}.bind(this));

Integration of node-whatsapi in meteor

I want to be able to nose whatsapi in meteor. I am using
latest stable meteor
node-whatsapi
arunoda´s meteorhacks:npm
and can get the past the basics:
On meteor server startup, I have:
whatsapi = Meteor.npmRequire('whatsapi');
wa = whatsapi.createAdapter({
msisdn: '....',
username: '....',
password: '....',
ccode: '....'
});
wa.connect(function connected(err) {
if (err) {console.log(err); return;}
console.log('Connected');
wa.login(logged);
});
function logged(err) {
if (err) {console.log(err); return;}
console.log('Logged in');
wa.sendIsOnline();
};
... which let me send and receive messages with a method call to
wa.sendMessage(recipient, content, function(err, id) {
if (err) {console.log(err.message); return;}
console.log('Server received message %s', id);
});
The code bellow also works, logging received messages on the console. This sits inside server Meteor.startup:
wa.on('receivedMessage', function(message) {
console.log("From: " + message.from);
console.log(message.body);
});
My problem is that when I try to add store message.from or message.body into a collection, meteor gives me "Meteor code must always run within a Fiber" error")
wa.on('receivedMessage', function(message) {
console.log("From: " + message.from);
console.log(message.body);
Recipients.insert({msgfrom: message.from});
});
Help!
Use Meteor.bindEnvironment to wrap any callback given out by your npm module. It will wrap the callback into a 'Fiber' so you can run Meteor code in it.
For example:
wa.on('receivedMessage', Meteor.bindEnvironment(function(message) {
console.log("From: " + message.from);
console.log(message.body);
Recipients.insert({msgfrom: message.from});
}));
What it does essentially is place the code in the callback into a Fiber.

How to stop polling in SignalR?

Is there any way to stop polling server in SignalR? I want to stop polling server if error occurs. Polling hubs is started with $.connection.hub.start(), so I assumed that it could be stopped with $.connection.hub.stop() or something like that. But it doesn't seem to work, polling continues even after calling stop(). Is there another way to stop pollling?
<script type="text/javascript">
var chatHub = $.connection.chatHub;
var connection = $.connection.hub;
chatHub.addMessage = function (message) {
$('#messages').append('<li>' + message + '</li>');
};
connection.error(function (error) {
$('#messages').append('<li>' + "error connecting: closing connnection" + '</li>');
connection.stop(); //This doesn't seem to work
});
connection.start();
</script>
If you're using hubs you can stop the hub's connection:
$.connection.hub.stop();
Firstly are you sure that is it necessary? If communication error occurs than obviously you want to retry it.
However, I looked into the source code and I mean that especially in error handler it is not possible call .stop() command. Respectively it has no effect because after handler function is finished than the communication is automatically reinitialized two second after.
See jquery.signalR.js (line 340):
$(instance).trigger("onError", [data]);
window.setTimeout(function () {
poll(instance);
}, 2 * 1000);
I found one workaround: In handler function throw an exception, which cause that poll is not reinitialized:
connection.error(function (error) { //$.connection.hub.error()
$('#messages').append('<li>' + "error connecting: closing connnection" + '</li>');
throw "Close SignalR connection";
});

Resources