Synced Cron Expire on Simple Schema

95 views Asked by At

I'm having some trouble setting up a cron job with percolate:synced-cron package to expire collection entries based on simple schema date and time fields. Is there another way to do this, or am I doing something wrong?

I'm receiving the following error below:

TypeError: Posts.find(...).toArray is not a function

Synced Cron Code

SyncedCron.start();


SyncedCron.add({
  name: 'Expire Events',
  schedule: function(parser) {
    // parser is a later.parse object
    return parser.text('every 15 minutes');
  },
  job: function() {
    expireToday = Posts.find ({
      date: new Date().toISOString().substring(0,10)
    }).toArray();
    console.log(expireToday);
    for (i = 0; i < expireToday.length; i++) {
      expireId = expireToday.eq(i)._id;
      console.log(expireId);
      if (expireToday.eq(i).time < new Date().toTimeString().substring(0,5)) {
        Posts.deleteOne({_id : expireId});
      }
    }
  }
});

Simple Schema Coffee Code

Schemas.Posts = new SimpleSchema
    title:
        type:String
        max: 60
        optional: true

    content:
        type: String
        optional: true
        autoform:
            rows: 5

    createdAt:
        type: Date
        autoValue: ->
            if this.isInsert
                new Date()

    updatedAt:
        type:Date
        optional:true
        autoValue: ->
            if this.isUpdate
                new Date()


    time:
        type: String
        optional: false
        autoform:
            afFieldInput:
                type: 'time'


    date:
        type: String
        optional: false
        autoform:
            afFieldInput:
                type: 'date'


    owner:
        type: String
        regEx: SimpleSchema.RegEx.Id
        autoValue: ->
            if this.isInsert
                Meteor.userId()
        autoform:
            options: ->
                _.map Meteor.users.find().fetch(), (user)->
                    label: user.emails[0].address
                    value: user._id

Example mongo date and time

"date" : "2017-09-10"
"time" : "01:01"
2

There are 2 answers

0
Michel Floyd On

See this related post

Going from dates to strings isn't great for searching in mongodb. If you want documents that expire today then you want to define today as going from midnight to midnight. You can also delete in bulk when running code on the server (SyncedCron jobs always run on the server).

SyncedCron.add({
  name: 'Expire Events',
  schedule: function(parser) {
    return parser.text('every 15 minutes');
  },
  job: function() {
    let todayStart = new Date();
    todayStart.setHours(0,0,0,0);
    let todayEnd = todayStart.setHours(23,59,59,999);
    Posts.remove ({ date: {$gte: todayStart, $lte: todayEnd });
  }
});

But this assumes you are storing datetimes in mongodb datetime fields, not as strings (which by the way, you should absolutely do, if nothing else but to gain timezone support).

If you want to use your schema with your date and time as strings then you can do:

SyncedCron.add({
  name: 'Expire Events',
  schedule: function(parser) {
    return parser.text('every 15 minutes');
  },
  job: function() {
    let today = new Date().toISOString().substring(0,10);
    let now = new Date().toTimeString().substring(0,5);
    Posts.remove ({ date: today, time: { $lte: now });
  }
});
1
Mikkel On

The error message is telling you that this failed:

expireToday = Posts.find ({
  date: new Date().toISOString().substring(0,10)
}).toArray();

It means that your Posts.find() didn't return anything that could be converted to an array.

It returns a cursor, maybe you meant to add a .fetch() to get an array of objects?

In either case you should check the return of a call like this to make sure it is returning what you expect - just basic defensive coding practice