Running server-side background tasks


#1

Hello,

I am developing an application where I need to run some server-side tasks at regular intervals. These tasks basically call existing methods on the server side, and also depends on user preferences.

I tried so far with basic Meteor.setInterval() functions and also cron packages (like easycron), but I always run into problems. For example, when using cron jobs, and calling a method from there, I always run into the same problem:

Meteor.userId can only be invoked in method calls. Use this.userId in publish functions.

Anybody knows how to solve this, and call methods from cron jobs just like you would from the client side?

Thanks!


#2

Meteor.userId points to the currently logged in user calling the method. Either you are trying to access Meteor.userId in your interval function or your method. When the server calls a function there is no Meteor.user you could refer to. Could you post your code?

We have been using Meteor.setInterval without a problem for sending out emails (for example notifications for chat messages) and calculating statistics every hour. What are you trying to achieve?


#3

Hello Valentin,

Thanks so much for your answer. Now I understand why I can’t get Meteor.userId. Here is the code example:

autoInvesting: function() {

    if (Meteor.user().profile.autoInvestRunning) {
      Meteor.users.update({_id: Meteor.user()._id}, { $set: {"profile.autoInvestRunning": true} }, function(error) {
        if (error) {console.log(error);}
      });

      var user = Meteor.user();

      Meteor.setInterval(function() {
        if (user.profile.autoInvest) {
          console.log('AutoInvest!');
        }
        if (!user.profile.autoInvest) {
          console.log('Do nothing');
        }
      }, 1000);
    }
  
  }

Basically, I am building an auto-investment app for Peer-to-Peer lending platforms. So if the user select the auto-invest preference, the server should then check for possible new investments at regular intervals.

Would it work if I just run through all users in the method called at regular intervals, and check each user preference individually ? Thanks!


#4

That is actually the only way you can do it. Since there is no “current user” you have to give the server something else to work with. You can do something like this:

Meteor.setInterval(function() {

    Meteor.users.find({
        autoInvesting: true
    }).fetch().forEach(function(user) {

   //Do what you want to do, e.g. call another function to handle investing
   //user points to a single user and can be used just like Meteor.user()
   

    });

 // Do some clean up etc. after the main loop
}, 3600000);

You have to watch out for memory leaks when using interval functions, but we have not had any problems with that so far. Also keep in mind that as soon as you deploy to more than 1 instance (or servo, dyno etc) this code will get executed on every instance ! At that point the easiest solution would be to let a separate instance handle all the periodic tasks.


#5

Thanks! That did it for me, works perfectly now.