Question

I'm trying to figure out the best way to perform a task, e.g. send an email to a user, in the future.

My idea is to store (in a database along with users data) when the email needs to be sent, and on a daily basis check what users need emails sent, and use Meteor's Timer functions.

// 7 hours in millisec.
Meteor.setTimeout( function() {
    Meteor.call( "sendReminderEmail", ... );
}, 2.52e+7 );

The problem that I see is having too many timers set up, and hindering performance. What is a good solution?

Edit: Basically my use case includes the user creating an event, which they set as a long term event or short term(based on days, weeks, or months), and they receive a follow-up on that event depending on the duration.

I guess I could check every hour, but that seems like a problem with equal cost. Is there a Meteor specific way to do this? Or just a better concept?

Edit2: Ok, I've realized that accurracy isn't that important for my problem, so I'm thinking of setting one timer per timezone, which would send bulk emails. If the user has a long term event and their reminder is this week, than send it now. Basically it depends on duration of event and timezone of user.

So my updated question is, how do I run something on a daily basis, with my problem in mind?

Was it helpful?

Solution

Let's say you want to execute a code at 9am today and now is 8am, you could create a timeout to match the minutes in the targeted time and then create a interval of 1 hour and at each execution check if the time is 9am, if it's, execute.

in this small scale example, I'm executing executeMe() when the clock shows 9 seconds:

Live Test: http://jsbin.com/ikulok/4/edit

<body>
Last run: <span id="time"></span><br>
Next execution: <span id="target"></span>
<script type="text/javascript">
    function executeMe(){
      alert("9 seconds!");
    }
    var timeout = null;
    var interval = null;
    function timer(){
      var now = new Date();
      document.getElementById('time').innerHTML = now;
      document.getElementById('target').innerHTML = new Date(now.getTime()+ 1000);
      //console.log("timer()", now);

      if(now.getSeconds() == 9)
        setTimeout("executeMe();",1); // async

      if(interval == null)
        interval = setInterval("timer()",1000);
    }

    var now = new Date();
    var target = new Date(now.getFullYear(),now.getMonth(),now.getDate(),now.getHours(),now.getMinutes(),now.getSeconds()+1,0);
    //console.log("now", now);
    //console.log("target", target);
    //console.log("diff", target.getTime() - now.getTime());
    document.getElementById('target').innerHTML = target;
    timeout = setTimeout("timer()", target.getTime() - now.getTime() );
  </script>


If you want to run the timer() every hour instead of every second, just adjust the target and the setInterval() and of course your conditions

Live Test: http://jsbin.com/ikulok/3/edit

<body>
  Last run: <span id="time"></span><br>
  Next execution: <span id="target"></span>
<script type="text/javascript">
    function executeMe(){
      alert("1:20am!");
    }
    var timeout = null;
    var interval = null;
    function timer(){
      var now = new Date();
      document.getElementById('time').innerHTML = now;
      document.getElementById('target').innerHTML = new Date(now.getTime()+ 1*60*60*1000);
      //console.log("timer()", now);

      if(now.getHour() == 1)
        setTimeout("executeMe();", 20*60*1000); // !!!! this will execute at 1:20am

      if(interval == null)
        interval = setInterval("timer()",1*60*60*1000); // !!!! repeat every hour
    }

    var now = new Date();

    // !!!! targeting next exact hour
    var target = new Date(now.getFullYear(),now.getMonth(),now.getDate(),now.getHours(),now.getMinutes()+1,0,0);
    //console.log("now", now);
    //console.log("target", target);
    //console.log("diff", target.getTime() - now.getTime());
    document.getElementById('target').innerHTML = target;
    timeout = setTimeout("timer()", target.getTime() - now.getTime() );
  </script>
</body>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top