[solved] Dynamic publications and unsubscribing


#1

I’m having a bit of an issue with publications/subscriptions. What I want to do is modify the subscription on the fly (replace the current sub with a new one). A good example of this would be a subscription to calendar events. The following code will use a YYMM date code to subscribe to all events for this month.

Meteor.publish("calendar_events", function(c){
  for(var i=0; i < c.length; i++)
     check(c[i], String);

  var low = (parseInt(c[1]))*100;
  var high = ((parseInt(c[1])+1)*100)-1;
  return db.calendar_events.find({"f_id" : c[0], date: { $gt: low, $lt: high}});
});

When I change months I can subscribe to a new publication via via

onMonthChange: function(month) {
  self.subscribe("calendar_events", 
        [feature._id, month.format('YYMM')]);
  update_calendar();
}

The issue with this is the fact that I’m still subscribed to all previous subscription calls for “calendar_events”. I imagine this is the desired functionality, but I want to change the subscription rather than create a new one each time it is called.

I have a potential solution that I will be trying when I get some time later. Publish would be modified to…

Meteor.publish("calendar_events", function(c){
  for(var i=0; i < c.length; i++)
     check(c[i], String);
  if(c[1].length > 0){
     var low = (parseInt(c[1]))*100;
     var high = ((parseInt(c[1])+1)*100)-1;
     return db.calendar_events.find({"f_id" : c[0], 
                 date: { $gt: low, $lt: high}});
   }
   else{
      this.stop();
   }
});

I would then do something like this when I want to unsubscribe to the current “calendar_events” and subscribe to new ones.

   self.subscribe("calendar_events", 
            [feature._id, ''], subscribe_new_month);

   ...

   function subscribe_new_month(){
      template.subscribe("calendar_events", 
            [feature._id, new_month]);
      update_calendar();
   }

It seems like it would work, but it has a hackish feel to it. Is there a “correct” way to do this? “this.stop” was the only thing I found in the meteor docs in terms of unsubscribe.

Thanks!


#2

your text is huge so I didn’t read it through, but I think this will help you out: https://www.discovermeteor.com/blog/template-level-subscriptions/


#3

You could try using template subscriptions. I think that’s what are going to want along with a reactive data source.
I imagine that it will look something like this.

var monthVar = new ReactiveVar("january");
Template.foo.onCreated(function(){
    var self = this;
    self.autorun(function(){
      var month = monthVar.get();
      self.subscribe("calendar_events", [feature._id, ""], month);
    })
});

Template.foo.events({
  'click button':funciton(e){
    monthVar.set(e.currentTarget.value);
  }
})

What’s happening is every time you change your month you are triggering the autorun in the onCreated method to run again. Instead of creating more publications which is bad for performance, you are simply changing the publication.


#4

I think the majority of my problem is that I didn’t/don’t fully understand the subscription model. It looks like I shouldn’t be manually removing old subs.