Reset a boolean everyday at 00:00

Hi,

Each one of my users have a checkbox that they can turn on.

I would like all these to be reset to unchecked everyday, let’s say at midnight automatically.

What is the cleanest way to achieve this?

I have thought of _ensureIndex with Expireat, but it deletes the user completely (and not only the true variable). Another way could be using Meteor startup function?

Thanks

Michael

1 Like

How about synced-cron?

Another way to do it without running a cron job is to store the last day at which they checked the box, and at runtime check if that is today or not.

4 Likes

You can try this package https://atmospherejs.com/vsivsi/job-collection.

My think about that is a “task”, that run every day, one “server method”, so:

The Method: (to run and change the boolean value, run only on server side, not called from client)

Meteor.methods({
    resetBoolean: function(userId) {
        this.unblock();
        
        // Check connection before run
        if (this.connection === null) {
            if (!userId) {
                throw new Meteor.Error('No user ID found!');
            }
            
            var result = Meteor.users.update(userId, {$set: {boolean: false}}, function(error) {
                if (error) {
                    throw new Meteor.Error(error);
                }
            });
            return result;
        } else {
            throw new Meteor.Error('server-only-method', 'Sorry, this method can only be called from the server.');
        }
    }
});

Define the “jobs collection”, create the task and run in “auto mode”:

// Create jobs collection
var myJobs = JobCollection('myJobQueue');

// Create the "Job" (task)
var runJobs = myJobs.processJobs(['resetBoolean'], function(job, callback) {
    var userId = job.data.userId;
    Meteor.call('resetBoolean', userId, function(error) {
        if (error) {
            job.fail(error);
        } else {
            job.done();
        }
        callback();
    });
});

// Run the Job in "auto mode"
myJobs.find({type: 'resetBoolean', status: 'ready'}).observe({
    added: function() {
        runJobs.trigger();
    }
});

Now you can insert new Job (task) to run:

// Insert new Job to run, with user ID
var resetBoolean = new Job(myJobs, 'resetBoolean',  {userId: 'xxxxxxx'});
resetBoolean
    .priority('normal') // Priority
    .retry({
        retries: 5, // Try 5 times before set failed
        wait: 15 * 60 * 1000 // 15 minutes between attempts
    })
    .repeat({
        schedule: jc.later.parse.text('at 00:00 am'); // https://bunkat.github.io/later/parsers.html#text
    });    
    .save(); // Save on "jobs collection"

Done, now after you add new “jobs” with the user ID will do this job automatically, you can check this collection on database and see. But I recommend that you learn all documentation, also look for security issues, I show just an example, this work for me.

Thanks for the answers, will try to implement.

Just to let you know, I have found a very simple package doing the job:

chfritz:easycron

Code on server side:


var onceEveryDay = new Cron(function() {

Meteor.users.update({"profile.status":true},{$set: {"profile.status": false}},{multi: true});

}, {
    minute: 0,
    hour: 1
});

Thanks everyone for the input, it put me on the way.

2 Likes

Good to know, I will look this package, thanks too.

PS: Jobs Collection is not only a cron, but more complex way to create tasks and run, etc.

Little update: apparently it only works if an instance of the app is running.

Any clue on how to arrange this?

@sugoke I think the package “chfritz:easycron” run the task based on current time, that started the function (app start). The other that I suggest can run delayed tasks, so if you need reset the value today, but exactly in this time your app stopped, then after your app back will run all delayed tasks, so will reset all values that need yet - and you can check the value before change it, on your task function.

Just to you know, the Jobs Collection package save all “tasks” on database, so every time that your app run, and need be running, it will get the tasks not completed from database and do that. But all packages inside your app will need an app instance running, server mode. To work without your app a live need be other service, not a package, you know? I hope you get this and solve your issue. Thanks.

I am thinking, the easiest could be to test who is the first visitor of the day.

And if you are the first visitor, your app will reset all checkboxes of all users.

Will have a look at these possibilities.