Force Meteor to Update on Remote Changes? - javascript

I have a meteor app that's being modified via an external API. The API modifies the mongodb that the Meteor app reads from. The problem I'm running into is that the changes the API are making to the database are not being rendered as quickly as I'd like them to be on my meteor app. If I post new data to my API every 10 seconds, my meteor app seems to only be updating every 30 seconds. How can I increase the rate at which meteor updates/listens to changes? Below is a sample of some code I wrote.
UsageData = new Mongo.Collection('UsageData');
if (Meteor.isClient) {
// This code only runs on the client
angular.module('dashboard', ['angular-meteor']);
angular.module('dashboard').controller('DashboardCtrl', ['$scope', '$meteor',
function($scope, $meteor) {
$scope.$meteorSubscribe('usageData');
$scope.query = {};
$scope.data = $meteor.collection(function() {
return UsageData.find($scope.getReactively('query'), {
sort: {
createdAt: -1
},
limit: 1
});
});
}
]);
}
// This code only runs on the server
if (Meteor.isServer) {
Meteor.publish('usageData', function() {
return UsageData.find({}, {
sort: {
createdAt: -1
},
limit: 20
});
});
}

Have you provided the OpLog URL to your meteor backend?
If not, then meteor is using the poll-and-diff algorithm which is
expensive (cpu & memory)
runs only every 10 seconds (because of 1.)
By using MongoDB OpLog it will run immediately.
This should be useful regarding OpLog & Meteor
https://meteorhacks.com/mongodb-oplog-and-meteor
Meteor 0.7 blog post, when the introduced oplog for the first time
http://info.meteor.com/blog/meteor-070-scalable-database-queries-using-mongodb-oplog-instead-of-poll-and-diff

Related

How to use same DB for two ddp connected applications

I have connected two meteor applications via DDP. I expected to get the DB data also on the second service application, but I don't get any data.
As both is running on server side I didn't do any subscription - which I think I don't have to in this example.
What am I doing wrong?
Starting main web application: meteor (which should load mongodb on port 3001)
Starting service application: MONGO_URL=mongodb://localhost:3001/mydb meteor --port 3100
Web (main)
/server/main.js
Examples = new Mongo.Collection('examples');
var serviceConn = DDP.connect("http://localhost:3100");
console.log(Examples.find().count()); // Returns 21
Service 1
/server/main.js
Examples = new Mongo.Collection('examples');
console.log(Examples.find().count()); // Returns 0 !
So why can't I get the collection data on the service application as it gives me 0 results?
Try this in your service application:
const con = DDP.connect('http://localhost:3000');
Examples = new Mongo.Collection('examples', {
connection: con,
});
console.log(Examples.find().count());
Remember to start your main application first

Running background tasks in Meteor.js

This is my scenario:
1. Scrape some data every X minutes from example.com
2. Insert it to Mongodb database
3. Subscribe for this data in Meteor App.
Because, currently I am not very good at Meteor this is what I am going to do:
1. Write scraper script for example.com in Python or PHP.
2. Run script every X minutes with cronjob.
3. Insert it to Mongodb.
Is it possible to do it completely with Meteor without using Python or PHP? How can I handle task that runs every X minutes?
There are Cron like systems such as percolate:synced-cron for Meteor. There, you could register a job using Later.js syntax similar to this example taken from the percolate:synced-cron readme file:
SyncedCron.add({
name: 'Crunch some important numbers for the marketing department',
schedule: function(parser) {
// parser is a later.parse object
return parser.text('every 2 hours');
},
job: function() {
var numbersCrunched = CrushSomeNumbers();
return numbersCrunched;
}
});
If you want to rely on an OS level cron job, you could just provide an HTTP endpoint in your Meteor.js application that you could then access through curl at the chosen time.
I can suggest Steve Jobs, my new package for scheduling background jobs in Meteor.
You can use the register, replicate, and remove actions
// Register the job
Jobs.register({
dataScraper: function (arg) {
var data = getData()
if (data) {
this.replicate({
in: {
minutes: 5
}
});
this.remove(); // or, this.success(data)
} else {
this.reschedule({
in: {
minutes: 5
}
})
}
}
})
// Schedule the job to run on Meteor startup
// `singular` ensures that there is only pending job with the same configuration
Meteor.startup(function () {
Jobs.run("dataScraper", {
in: {
minutes: 5
},
singular: true
})
})
Depending on your preference, you can store the result in the database, as part of the jobs history, or remove it entirely.

Meteor - Server-side API call and insert into mongodb every minute

I am in the process of learning Meteor while at the same time experimenting with the TwitchTV API.
My goal right now is to call the TwitchAPI every minute and then insert part of the json object into the mongo database. Since MongoDB matches on _id and Twitch uses _id as its key I am hoping subsequent inserts will either update existing records or create a new one if the _id doesnt exist yet.
The call and insert (at least the initial one) seem to be working fine. However, I can't seem to get the Meteor.setTimeout() function to work. The call happens when I start the app but does not continue occurring every minute.
Here is what I have in a .js. file in my server folder:
Meteor.methods({
getStreams: function() {
this.unblock();
var url = 'https://api.twitch.tv/kraken/streams?limit=3';
return Meteor.http.get(url);
},
saveStreams: function() {
Meteor.call('getStreams', function(err, res) {
var data = res.data;
Test.insert(data);
}
}
});
Deps.autorun(function(){
Meteor.setTimeout(function(){Meteor.call('saveStreams');}, 1000);
});
Any help or advice is appreciated.
I made the changes mentioned by #richsilv and #saimeunt and it worked. Resulting code:
Meteor.startup(function(){
Meteor.setInterval(function(){Meteor.call('saveStreams');}, 1000);
});

How to push notifications with angular.js?

I have been building a simple application to learn angular.js. So far I hooked up all the pieces in the MEAN stack and I am able to save and retrieve data from Mongo.
The app is essentially a todo list. The user can create a project and inside the project create "cards" with "todos" which can then be moved from state to state ("backlog", "in progress", "complete", etc.)
I would like to be able to push the notifications to all the people who are connected to tell their apps that a refresh is needed to get the latest todos. In other words, let's say that user A adds a new card to project A, I would like to send a message out to all users who are currently watching project A so that their application issues a project refresh to get the latest and greatest.
Any suggestions on how to proceed? Which technology, if any, I need to add to the MEAN stack to be able to do something like this?
Thanks in advance
Since you're on the MEAN stack, the standard recommendation in Node would be to use the Socket.IO API.
They provide the following example of two way messaging (which would facilitate your push messages very easily):
Client
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io.connect('http://localhost');
socket.on('news', function (data) {
console.log(data);
socket.emit('my other event', { my: 'data' });
});
</script>
Server
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(80);
function handler (req, res) {
fs.readFile(__dirname + '/index.html',
function (err, data) {
if (err) {
res.writeHead(500);
return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}
io.sockets.on('connection', function (socket) {
socket.emit('news', { hello: 'world' });
socket.on('my other event', function (data) {
console.log(data);
});
});
It will use websockets where possible, and fallback to AJAX long polling or Flash polling in browsers where there is no websocket support.
As for integrating with Angular, here's a good blog post on Socket.IO and Angular:
I'll be writing about how to integrate Socket.IO to add real-time
features to an AngularJS application. In this tutorial, I'm going to
walk through writing a instant messaging app.
If you're already working with Express, you should check out express.io.
It has a bunch of cool features like Session support and the ability to forward normal HTTP routes to realtime routes.
Here is a module we have written for getting AngularJS push notifications working in PhoneGap / Cordava (with full instructions):
http://www.scorchsoft.com/blog/free-angularjs-cordova-push-notification-plugin/
Simply download the example code and install. There is also code included for setting up the pushing component in PHP.
Why not with HTML5 Notification API....
export default class NotificationService {
/**
* Constructor of the class.
*
*/
constructor() {}
showPushNotification(title: string = '', message: string, iconPush) {
if (window.Notification && Notification.permission !== "denied") {
Notification.requestPermission(function(status) {
var n = new Notification(title, {
body: message,
icon: iconPush
});
});
}
}
}

Number of visitors to my webpage

I am trying to create a webpage using meteor which records the number of visitors to the webpage. The webpage should record and display the number of people who visited the webpage.I am just a beginner to meteor and web design ,i have no experience whatsoever in using meteor and this is my first attempt. So any help is appreciated. Thank you in advance.
You can also run AWstats
http://awstats.sourceforge.net/
and install tutorial here:
http://www.youtube.com/watch?v=dOF4MDn_TI0
you can have something like this
collections\system.js
this.System = new Meteor.Collection('system');
Meteor.methods({
pageViewInc: function() {
System.update({ config: true }, { $inc: { 'stats.pageviews': 1 } });
}
});
if (Meteor.isServer) {
isSystemExist = System.findOne({ config: true });
if (!isSystemExist) {
options = {
stats: {
pageviews: 0
},
config: true
};
System.insert options
}
}
and somewhere you can have a function use to Meteor.call 'pageViewInc'
if u use Meteor-Iron-Router
you can have call in 'after' callback
Meteor.call('pageViewInc');
you can make similar method to Posts Collection.
or there's a meteor-collection-hooks packages
it has after findOne hook you can do it by server side.

Categories